我见过使用long
/ jlong
来允许Java对象保留C++指针的示例:
class Foo { private native long create(); } struct Foo { }; JNIEXPORT jlong JNICALL Java_Foo_create (JNIEnv *, jobject) { return (jlong) (new Foo); }
这让我觉得有点紧张,因为它假设一个指针适合64位; 这在OS/400上是不真实的.
是否有更安全的解决方案,例如封装C++指针的Java标准库类?
您可以使用哈希表存储指针并将该哈希表的键返回给用户。喜欢:
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; }
现在,您可以使用一个句柄从哈希图中获取指针:
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 } }
此外,此方法还将帮助您检查对象是否已删除或删除仍然存在的所有Foo对象。缺点是访问哈希图以获取指针会降低性能。同样,您可能应该从多线程访问中保护句柄映射,或者使用线程安全的映射实现。
另外,如果您需要为Java实现包装器,我建议考虑使用SWIG(简化包装器和接口生成器)。