2012-07-16 97 views
4

我包装使用JNI一些C++代码,偶然发现了以下工厂函数:传递的std ::的unique_ptr到JNI

std::unique_ptr<MetricPlanner> create_metric_planner(*arguments*) 

我需要一个参考传递给规划者这个函数创建回Java以供以后使用,但我对 a)如何将其传回,以及 b)当它传递时会发生什么。

通常情况下,我已经通过像这样:

Director *DIRECTOR = new Director(arguments); 
return (jlong)DIRECTOR; 

,它就像一个魅力的工作。

有人可以解释类似的过程,当使用返回这种类型的指针的工厂函数,而不是一个普通的构造函数时,用JNI引用对象?

回答

2

由于您将create_metric_planner函数的返回值传递给Java,并稍后使用它,因此您不希望unique_ptr在范围结束时销毁返回值。要做到这一点,您必须致电unique_ptr::release

return (jlong)create_metric_planner(...).release(); 

不要忘了,在某些时候,当你使用该函数返回的对象来完成,必须delete它(或调出你正在使用的库提供了一些删除器功能)。

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/