5

我正在用 JNI 包装一些 C++ 代码,并偶然发现了以下工厂函数:

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

我需要将对该函数创建的计划器的引用传递回 Java 以供以后使用,但我对 a) 如何将其传递回来以及 b) 一旦传递它会发生什么感到困惑。

通常,我一直这样通过:

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

它就像一个魅力。

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

4

2 回答 2

3

由于您将create_metric_planner函数的返回值传递给 Java,然后再使用它,因此您不希望unique_ptr在其作用域结束时破坏返回值。为此,您必须调用unique_ptr::release.

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

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

于 2012-07-16T21:55:45.510 回答
0

我使用以下代码创建、使用和删除带有 a 的对象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/ac-smart-pointer-wrapper-for-use-with-jni/

于 2017-08-31T21:58:02.283 回答