android - JNI : map jobject to native c++ object

标签 android c++ android-ndk java-native-interface

我使用常规的 std::map 将 jobject 映射到 C++ 对象。这种方法的问题在于它可能无法用于其他类型的引用,例如全局引用实际上是不同于常规局部引用的指针,即使它们引用同一个对象。比较两个引用是否引用同一个对象的正确方法是:

env->IsSameObject(jobj1, jobj2);

所以,我的问题是:将 jobject 映射到 C++ 对象的正确方法是什么?将 jobject 包装到某个重载 operator== 并调用 IsSameObject 的 c++ 类中的明显答复不是我正在寻找的答复。我想知道是否有办法做到这一点,而无需为每个比较操作在 JVM 和 native c/c++ 之间来回切换。

编辑:全局引用是jni全局引用,与c++引用无关。

EDIT2:我想澄清一下这段代码的问题是什么:

std::map<jobject, void *> jobjs;
jobject obj1, obj2;
... some code that sets these obj1 and obj2 to some Java objects.

jobjs[obj1] = new CppPeer;
CppPeer * = jobjs[obj1]; //OK...
if(objs.find(obj2) == objs.end()){
   assert(obj2 != obj1);
   //Here's the problem: here a new c++ CppPeer
   //created for obj2, but the problem is that 
   //even if obj1 != ob2 it doesn't mean that
   //they actually reference different java objects
   //On the next line error might happen
   jobjs[obj2] = new CppPeer; //maybe not OK here...
}

IsSameObject 的另一个问题是它使事情变得非常讨厌和困惑。不仅现在我需要保留指向 JVM 的指针,而且每当我需要比较 jobject 时,我都需要附加线程等以获得指向 JNIEnv 的指针以便能够检查 jobject

EDIT3:请注意,根据 android 文档,如果两个引用相等,您甚至不能假设它们引用同一个对象。我不知道这怎么可能,但有来自 Android 的 JNI 提示页面的部分:

One consequence of this is that you must not assume object references are constant or unique in native code. The 32-bit value representing an object may be different from one invocation of a method to the next, and it's possible that two different objects could have the same 32-bit value on consecutive calls. Do not use jobject values as keys.

最佳答案

免责声明:它闻起来。

在 Android 上,指针和 jint 的大小相同。考虑向您的 Java 类添加一个 int 字段以存储指向 native 对应部分的指针。在 JNI 方法中时,将其类型转换回指针。

为了稍微安全一点,对数据类型匹配做一个静态断言:

{char a[sizeof(void*) == sizeof(jint) ? 1 : -1]};

如果它是在一个没有它的系统上编译的,你会得到一个编译错误。

为了稍微减少气味,使用从 int 到对象的静态/全局 map,使用 ID 生成器,而不是对象指针存储相对唯一的(在进程生命周期内)Java 中的对象 ID对象。

关于android - JNI : map jobject to native c++ object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13040949/

相关文章:

android - 如何将 Android 库(AAR 文件)嵌入到电容器插件中?

android - startForeground() 不显示我的通知

c++ - c++中的叉积

android ndk和sdk兼容性问题(运行时链接器错误)

android - NDK冲突c/c++

android - 将 sqlite 数据库从设备复制到 PC

java - 在构建期间无法使 gradle 任务在 Java 中传递值

c++ - 打开根目录下的文本文件

c++ - CMake 链接静态库和 Glib 错误

android - 用 clang 而不是 gcc 构建 android?和 clang STL 库而不是 gnuSTL 库?