Android — JNI: сопоставить рабочий объект с родным объектом C ++

Я использую обычный std :: map для сопоставления рабочих мест с объектами c ++. Проблема с этим подходом состоит в том, что он может потерпеть неудачу для других типов ссылок, например, глобальные ссылки фактически отличаются от обычных локальных ссылок, даже если они ссылаются на один и тот же объект. Правильный способ сравнения, если две ссылки ссылаются на один и тот же объект:

env->IsSameObject(jobj1, jobj2);

Итак, мой вопрос: как правильно сопоставить рабочие объекты с объектами c ++? Очевидный ответ для переноса jobject в некоторый класс c ++, который перегружает operator == и вызывает IsSameObject, не тот ответ, который я ищу. Я хотел бы знать, есть ли способ сделать это, не переходя назад и вперед между 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 вы даже не можете предположить, что две ссылки ссылаются на один и тот же объект, если они равны. Я не знаю, как это возможно, но есть часть на странице советов по JNI для Android:

Одним из следствий этого является то, что вы не должны принимать ссылки на объекты
постоянны или уникальны в нативном коде. 32-битное значение, представляющее
объект может отличаться от одного вызова метода к
далее и возможно, что два разных объекта могут иметь одинаковые
32-битное значение при последовательных вызовах. Не используйте значения заданий в качестве ключей
.

1

Решение

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: пахнет.

На Android указатель и jint одинакового размера. Попробуйте добавить поле int в свой класс Java, чтобы сохранить указатель на нативный компонент. В методе JNI приведите его обратно к указателю.

Чтобы быть немного безопаснее, сделайте статическое утверждение при сопоставлении типов данных:

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

Если он скомпилирован в системе, где его нет, вы получите ошибку компиляции.

Для немного меньшего запаха, используйте статический / глобальный map от int до ваших объектов, используйте генератор идентификаторов и вместо указателя объекта храните относительно уникальные (в пределах времени жизни процесса) идентификаторы объектов в Java-объекте.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector