Java – is there a more portable way to encapsulate pointers than jlong in JNI?
I've seen an example of using long / jlong to allow Java objects to hold C pointers:
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 a pointer is suitable for 64 bits; This is not true on OS / 400
Is there a more secure solution, such as a Java standard library class that encapsulates C pointers?
Solution
You can use a hash table to store pointers and return the keys of this hash table to the user Like:
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; }
You can now get the pointer from HashMap using the handle:
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 } }
This method can also help you check whether the object has been deleted or delete all foo objects that still exist The disadvantage is that accessing HashMap to get pointers can degrade performance In addition, you should use multithreaded access or thread - safe mapping implementation to protect your handle mapping
Or, if you need to implement wrappers for Java, I suggest considering swig (simplified wrapper and interface generator)