2012-07-16 96 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/