Is there a more portable way in JNI than jlong ​​to encapsulate a pointer?

I saw examples of using long / jlong to allow a Java object to hold a pointer to C ++:

 class Foo { private native long create(); } struct Foo { }; JNIEXPORT jlong JNICALL Java_Foo_create (JNIEnv *, jobject) { return (jlong) (new Foo); } 

This makes me feel a little nervous because it assumes that the pointer will match 64 bits; which is not true, for example, on OS / 400.

Is there a safer solution, like a standard Java library class that encapsulates a pointer to C ++?

+7
java jni
source share
3 answers

You can use the hash table to store pointers and return the key of this hash table to the user. How:

  std::unordered_map<long, Foo*> handles; long newHandle = 0 ... JNIEXPORT jlong JNICALL Java_Foo_create (JNIEnv *, jobject) { Foo* ptr = new Foo; long handle = newHandle; handles.insert(std::pair<long, Foo*>(newHandle++, ptr)); return handle; } 

Now you can use the handle to get the pointer from the hash map:

 JNIEXPORT void JNICALL Java_Foo_use (JNIEnv *, jobject, jlong handle) { auto iter = handles.find(handle); if (iter != handles.end()) { Foo* ptr = iter->second; // use Foo* here } } 

Also this method will help you check if the object has already been deleted or delete all Foo objects that still exist. The downside is that accessing the hashmap to get a pointer can slow performance. In addition, you should probably protect your descriptor card from multi-threaded access or use a realistic implementation of the card.

Alternatively, if you need to implement shells for Java, I would recommend considering SWIG (simplified simplifier and interface generator).

+4
source share

Error checking skipped for brevity:

 JNIEXPORT jobject JNICALL Java_Foo_create(JNIEnv * env, jobject) { Foo* ptr = new Foo; return env->NewDirectByteBuffer(&ptr, sizeof(ptr)); } /* private */ const Foo* from_jobject(JNIEnv * env, jobject java_foo) { return (reinterpret_cast<Foo**>(env->GetDirectBufferAddress(java_foo)))[0]; } 

See also http://rkennke.wordpress.com/2007/07/30/efficient-jni-programming-iv-wrapping-native-data-objects/ .

+1
source share

Although a jobject defined as a pointer, it smells because it is not a valid JVM object. (I don't know if this will cause any problems if you are careful not to treat it as a JVM object.)

You can try the jobject returned by NewDirectByteBuffer . It grabs a pointer and creates a valid JVM object.

 JNIEXPORT jobject JNICALL Java_Foo_create (JNIEnv *env, jobject) { Foo *pFoo = new Foo(); return env->NewDirectByteBuffer(pFoo, sizeof(Foo)); } 

Also, be sure to consider life cycle management and other questions raised in the IvanMushketyk answer . And take a look at JNA (via JNAerator) and SWIG as an alternative to writing your own JNI code. Their output may not be portable, but their assembly processes may be.

0
source share

All Articles