我用JNI包装了一些C ++代码,偶然发现了以下工厂函数:
std::unique_ptr<MetricPlanner> create_metric_planner(*arguments*)
我需要将对此函数创建的计划程序的引用传递回Java以供以后使用,但我感到很困惑 a)如何将其传回去,和 b)一旦传递将会发生什么。
通常情况下,我一直这样过去了:
Director *DIRECTOR = new Director(arguments);
return (jlong)DIRECTOR;
它就像一个魅力。
当使用返回此类指针的工厂函数而不是普通的构造函数时,有人能解释用JNI引用对象的类似过程吗?
答案 0 :(得分:2)
由于您将create_metric_planner
函数的返回值传递给Java,然后再使用它,因此您不希望unique_ptr
在其作用域结束时销毁返回值。为此,您必须致电unique_ptr::release
。
return (jlong)create_metric_planner( ... ).release();
不要忘记,在某些时候,当你完成使用该函数返回的对象时,你必须delete
它(或调用你正在使用的库提供的一些删除函数)。
答案 1 :(得分:0)
我使用以下代码创建,使用和删除带有std::unique_ptr
的对象,同时保持Java端的引用(以保持对象保持活动状态,即使在切换活动时)。
创建对象并将指针传递给Java:
void Java_com_domain_project_activity_createObject(JNIEnv *env, jobject obj) {
Object* object = (std::makeUnique<Object>()).release();
env->SetLongField(obj, getPtrFieldId(env, obj), (jlong)object);
}
删除对象:
void Java_com_domain_project_activity_deleteObject(JNIEnv *env, jobject obj) {
Object* object = (Object*) env->GetLongField(obj, getPtrFieldId(env, obj));
delete object;
}
处理对象:
void Java_com_domain_project_activity_workOnObject(JNIEnv *env, jobject obj) {
Object* object = (Object*) env->GetLongField(obj, getPtrFieldId(env, obj));
// Work on object
}
最后保持指针存储在Java端:
jfieldID getPtrFieldId(JNIEnv * env, jobject obj)
{
static jfieldID ptrFieldId = 0;
if (!ptrFieldId)
{
jclass c = env->GetObjectClass(obj);
ptrFieldId = env->GetFieldID(c, "objPtr", "J");
env->DeleteLocalRef(c);
}
return ptrFieldId;
}
理想情况下,我不会将unique_ptr
用于这些情况,只使用普通指针,但我的项目中需要unique_ptr
。
我还发现这个网站非常有用:https://www.studiofuga.com/2017/03/10/a-c-smart-pointer-wrapper-for-use-with-jni/