Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In JNI, is there a more portable way than jlong to encapsulate a pointer?

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?

like image 369
Owen Avatar asked Dec 28 '13 05:12

Owen


1 Answers

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).

like image 177
Ivan Mushketyk Avatar answered Oct 20 '22 03:10

Ivan Mushketyk