4

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?

2
  • Are you sure about the files generated? For me swig also generated test_app.java (yes, I've tried compiling your module). Commented Mar 22, 2013 at 9:06
  • Yes, you are right. I forgot to mention test_app.java. Commented Mar 22, 2013 at 9:29

2 Answers 2

2

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 i.e.

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for your replay. When running swig -java test_app.i I get in return test_app_wrap.c, test_appJNI.java and SWIGTYPE_p_int.java. You are right about that native void print_hello. In my case print_hello method returns a STRING. I guess it will be native String print_hello(); Am I right?
Check the tutorial, it explains exactly what you have to do in order to get your JNI to work
I did check the tutorial. Thank you very much. In my case I do have the test_app_wrapper.c (created by swig). There is no need to create a new ctest.c (as it says in the tutorial). Could you tell me what is the path to the /path/to/jdk/headers ? Thank you!
1

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 ). E.g. 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 :)

9 Comments

I did edit my question. Can you please take a look? WHat do you mean by import test_app? THANK YOU!
I mean plain old Java import test_app;.
Oh wait, you don't need to import explicitly (I haven't used Java for ages now).
Just finished editing my answer - I think it's enough details now!
Thank you very much! You are a true HELPER!! I modified the HelloWorld.java file and run java -Djava.library.path= .HelloWorld from command line, but I still have the error: 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:3)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.