我使用常规 std::map 将 jobject 映射到 c++ 对象。这种方法的问题在于它可能对其他类型的引用失败,例如全局引用实际上是不同于常规局部引用的指针,即使它们引用同一个对象。比较两个引用是否引用同一个对象的正确方法是:
env->IsSameObject(jobj1, jobj2);
所以,我的问题是:将 jobject 映射到 c++ 对象的正确方法是什么?将 jobject 包装到重载 operator== 并调用 IsSameObject 的某个 c++ 类中的明显回复不是我正在寻找的回复。我想知道是否有办法做到这一点,而无需在每次比较操作中在 JVM 和本机 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 的指针,而且每当我需要比较作业时,我都需要附加线程等以获取指向 JNIEnv 的指针,以便能够检查作业
EDIT3:请注意,根据 android 文档,如果它们相等,您甚至不能假设两个引用引用同一个对象。我不知道这怎么可能,但Android的JNI提示页面中有一部分:
这样做的一个后果是,您不能假设对象引用在本机代码中是恒定的或唯一的。表示一个对象的 32 位值可能与一个方法的调用不同,并且有可能两个不同的对象在连续调用时可能具有相同的 32 位值。不要使用 jobject 值作为键。