简体   繁体   中英

java wrapper for .c code

I have the following c code:

test.c

#include <stdio.h>
#include <math.h>

int add (int a, int b)
{
    a=4;
    b=4;
    return a+b;
}

int add_pointer (int *a, int *b)
{
    printf("values of a,b: %d,%d \n",*a,*b);
return ((*a)+(*b));
}

char* print_hello()
{
    return "hello_world";
}

test.h

#ifndef TEST_H_
#define TEST_H_

int add(int a, int b);
int add_pointer (int *a, int *b);
char *print_hello();

#endif

main.c

#include "test.h"
#include <stdio.h>
#include <math.h>

int main()
{
    int a,b,c,d;
    char* rez;

    a=5;
    b=2;

    //int *r=&a;
    c= add(a,b);
    d=add_pointer(&a,&b);
    rez=print_hello();

    printf("sum is: %d and : %s %d \n",c,rez,d);
    return 0;
}

test_app.i

%module test_app

%{
#include "test.h"
%}

%include "test.h"

I want to create a java wrapper ofer this .c code. I would like later to use this wrapper in an android demo.

I did the following:

$: swig -java test_app.i

GIVES:

test_app_wrapper.c
test_app.java
test_appJNI.java
SWIGTYPE_p_int.java 

$: gcc -fpic -c test.c test_app_wrap.c -I /usr/lib/jvm/java-7-openjdk-amd64/include -I /usr/lib/jvm/java-7-openjdk-amd64/include/linux
$: gcc -shared test.o test_app_wrap.o -o libtest_app_wrap.so

UPDATE:

HelloWorld.java

      public class HelloWorld {
    native String print_hello(); /* (1) */
    static {
        System.loadLibrary("test_app_wrap"); /* (2) */
    }
    static public void main(String argv[]) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.print_hello(); /* (3) */
    }
}

When running:

$: javac HelloWorld.java 
$ java HelloWorld

I have:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no test_app_wrap in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1856)
    at java.lang.Runtime.loadLibrary0(Runtime.java:845)
    at java.lang.System.loadLibrary(System.java:1084)
    at HelloWorld.<clinit>(HelloWorld.java:4)

What am I doing wrong?

It seems you don't understand how jni works, check this tutorial:

Calling C code from Java using JNI

Your test_app_wrap doesn't exist, to use JNI you have to assign a particular name to your C functions, then make a Java class with native methods to call them ie

native String print_hello();

and, in the Java class, load the native library.

Then you will create a YourClass Java object and call the print_hello() native method

When you execute swig -java test_app.i , it creates some Java glue classes that you must include in your Java project. The main interface generated is named test_app.java and looks like this:

public class test_app {
  public static int add(int a, int b) {
    return test_appJNI.add(a, b);
  }

  public static int add_pointer(SWIGTYPE_p_int a, SWIGTYPE_p_int b) {
    return test_appJNI.add_pointer(SWIGTYPE_p_int.getCPtr(a), SWIGTYPE_p_int.getCPtr(b));
  }

  public static String print_hello() {
    return test_appJNI.print_hello();
  }

}

As you can see, it delegates all the calls to test_appJNI , which is also automatically generated, and acts as a glue to the native code (using native methods):

public class test_appJNI {
  public final static native int add(int jarg1, int jarg2);
  public final static native int add_pointer(long jarg1, long jarg2);
  public final static native String print_hello();
}

So, you should:

  • include both generated .java files in the project
  • ensure that you load the .so library with System.loadLibrary("test_app_wrap"); - you already do it
  • simply call test_app.print_hello()

Also, recommended reading: 21 SWIG and Java section from SWIG manual. The Preliminaries and A tour of basic C/C++ wrapping sections explain all the basics quite well.

The error you get indicates that JVM can't load the .so library. My first question would be if it compiled and linked properly. If you are sure you have libtest_app_wrap.so , it might not be on the path where JVM looks for it (check this - http://www.chilkatsoft.com/p/p_499.asp ). Eg for me it was necessary to add -Djava.library.path=. to Java command line:

java -Djava.library.path=. HelloWorld

For reference - I've modified your HelloWorld.java file:

public class HelloWorld {
    static {
        System.loadLibrary("test_app_wrap"); 
    }
    static public void main(String argv[]) {
        test_app.print_hello();
    }
}

Hope that helps :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM