c++ - Using non-static objects in jni in java -
i trying learn jni, , wondering how make java object have values associated in jni c++ layer. have java code.
public class test { static { runtime.getruntime().loadlibrary("jnitests"); } public native void setvalue(int value); public native int getvalue(); public static void main(string[] args) { test test1 = new test(); test1.setvalue(34); test test2 = new test(); test2.setvalue(23); system.out.println(test1.getvalue()); } }
so trying enable each test object store value in jni using setvalue , getvalue, using c++ code.
#include <jni.h> #include "test.h" int value; jniexport void jnicall java_test_setvalue(jnienv *, jobject, jint newvalue) { value = newvalue; } jniexport jint jnicall java_test_getvalue(jnienv *, jobject) { return value; }
however, problem when use setvalue on test2 , print test1's value has changesd set test2 to. how fix this. tried mapping each jobject int value did not work either.
a possible solution may use of dynamically allocated structure in native code. work, have allocate (for example, in constructor) memory holds structure. address of structure passed java part , stored in java object. then, getvalue
, setvalue
, parameter added holds memory address of allocated structure, can use storing value. when destroying object, have free memory manually.
using code, native part may like:
#include <cstdlib> #include <jni.h> #include "test.h" struct data { int value; }; jniexport void jnicall java_test_setvalue0(jnienv *, jobject, jlong address, jint newvalue) { struct data *ptr = (struct data *)address; ptr->value = newvalue; } jniexport jint jnicall java_test_getvalue0(jnienv *, jobject, jlong address) { struct data *ptr = (struct data *)address; return ptr->value; } jniexport jlong jnicall java_test_construct0(jnienv *, jobject) { struct data *ptr = (struct data *)malloc(sizeof(*ptr)); return (jlong)ptr; } jniexport void jnicall java_test_destruct0(jnienv *, jobject, jlong address) { struct data *ptr = (struct data *)address; free(ptr); }
and java part like:
public class test { static { runtime.getruntime().loadlibrary("jnitests"); } private long address; private native long construct0(); private native void destruct0(long address); private native void setvalue0(long address, int value); private native int getvalue0(long address); public test() { this.address = this.construct0(); } @override public void finalize() { this.destruct0(this.address); super.finalize(); } public void setvalue(int value) { this.setvalue0(this.address, value); } public int getvalue() { return this.getvalue0(this.address); } public static void main(string[] args) { test test1 = new test(); test1.setvalue(34); test test2 = new test(); test2.setvalue(23); system.out.println(test1.getvalue()); } }
i renamed native methods introduce address
parameter without api change.
Comments
Post a Comment