0

Ok say I have this C function

int image(int *w, int *h) {
  *w = 100;
  *h=200;
}

How can I wrap this in JNI? I am developing for the Android platform.

jint Java_com_test_image(JNIEnv *env, .....) {
}
rukiman
  • 597
  • 10
  • 32

3 Answers3

1

I would point out your C code is declared as returning an int but does not have a return statement.

That aside you have two options IMO :

  • Store and return the pointer values ( my preferred method is in a jbyteArray ) and let Java pass them around. You would also need a JNI function to actually return a jint to dereference that stored pointer as well ( i.e. to get 'w' from '&w' ). I think this is not the best way to go.

  • Use a Java Integer object and pass that from Java. Your JNI code then has something it can update the value of without a problem. Java passes objects by reference so this is the most logical conceptual choice, I think.

As is pointed out in a comment ( and forgotten by me in my original answer :-( ), Java's Integer class is immutable ( no changing value ) so you the simplest way is define a new class :

public class mutableInt
{
    int value ;

    public void setValue( int newval )
    {
        this.value = newval ;
    }

    public int getValue()
    {
        return this.value ;
    }
}

So using the second option, your java side declaration your be something like :

int public native image( mutableInt w, mutableInt h ) ;

On the native side you would use JNI functions to alter the values of the w and h objects passed to JNI using the appropriate methods and calculate your jint return value in whatever way you want. You'd use JNI to get and set the values of the paramters using the setValue() and getValue() method.

  • 1
    *Use a Java Integer object and pass that from Java.* and *On the native side you would use JNI functions to alter the values of the w and h objects* No! Do **not** do this. The JVM considers `Integer` objects to be immutable. If you change the value held inside an `Integer` object from native code, the results are undefined. See http://stackoverflow.com/questions/5560176/is-integer-immutable – Andrew Henle Dec 04 '15 at 11:39
  • 1
    Quite correct. My mistake. Quick edit to answer to reflect your comments. Thanks. – StephenG - Help Ukraine Dec 04 '15 at 12:37
0

you might want to consider to return the Address as well as the Value to Java.

m.ding
  • 3,172
  • 19
  • 27
  • Can your provide an example? I don't quite follow. – rukiman Dec 03 '15 at 23:59
  • @rukiman Is it possible for your to change the C function or it is a C library? the easiest way is you have another level in C to wrap the function to take an int, then handle everything pointer related in C level. – m.ding Dec 04 '15 at 00:02
  • This is just an example. But essentially the C function will read some data and I want to return three integers back to the Java level. – rukiman Dec 04 '15 at 02:45
0

It's best to focus on creating a natural API and keep any ugliness in the bridging code.

class Point 
{
    public int x; // consider using accessor methods
    public int y;
}

Point getImagePosition() /* throws SomeException */;

getImagePosition could be:

  • the native method with all the bridging code in JNI, or
  • it could be partially implemented in Java to make the JNI easier (maybe using @StevenG's mutableInt or Integer)

Doing with getImagePosition as native, you would create a Point object with JNI calls and populate it. (You could also give it a constructor to populate it.)

The key to calling methods in JNI is to get the signature right. To do that, extract the info from the .class or .jar files. (Be sure to specify a classpath if you want your class.) Here is an example with a standard class:

javap -s java.awt.Point | grep -A 2 "Point("

You also have to know that that constructors are named "<init>".

So,

constructor = (*env)->GetMethodID(env, cls, "<init>", "()V");
Tom Blodget
  • 20,260
  • 3
  • 39
  • 72