I've seen examples of using a long
/jlong
to allow a Java object to hold onto a C++ pointer:
class Foo {
private native long create();
}
struct Foo { };
JNIEXPORT jlong JNICALL Java_Foo_create
(JNIEnv *, jobject)
{
return (jlong) (new Foo);
}
This makes me feel just a little bit nervous because it assumes that a pointer will fit in 64 bits; that is untrue for example on OS/400.
Is there a safer solution, for example a Java standard library class that encapsulates a C++ pointer?
You can use a hashtable to store pointers and return key of this hashtable to a 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;
}
Now you can use a handle to get pointer from the hashmap:
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 to check if an object was already deleted or to delete all Foo object that still exist. The drawbacks are that access to hashmap to get a pointer can decrease performance. Also you should probably guard with your handles map from multithread access or use thread-safe map implementation.
Alternatively, if you need to implement wrappers for Java, I would recommend to consider SWIG (Simplified Wrapper and Interface Generator).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With