将std::unique_ptr传递给JNI

5

我正在使用JNI封装一些C++代码,遇到了以下工厂函数:

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

我需要将这个函数创建的规划器的引用传回Java以供以后使用,但我很困惑:

  1. 如何将其传回?
  2. 一旦传递了它,会发生什么?

通常,我是这样传递的:

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

它运行得非常好。

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

2个回答

3

由于您将create_metric_planner函数的返回值传递给Java,然后稍后再使用它,因此您不希望unique_ptr在其作用域结束时销毁返回值。要实现这一点,您必须调用unique_ptr::release

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

不要忘记,在某个时刻,当你使用该函数返回的对象完毕后,你必须删除(delete)它(或者调用你正在使用的库提供的一些删除器(deleter)函数)。


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/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接