我使用常规的 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/