首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在JNI中的调用之间保持对象?

如何在JNI中的调用之间保持对象?
EN

Stack Overflow用户
提问于 2013-10-04 14:32:12
回答 2查看 1.2K关注 0票数 1

我有一个带有本地代码的Android应用程序。如何在调用本机方法之间保持对对象的引用?

代码语言:javascript
运行
复制
// 1: create native object and hold it
Object obj = jni_wrapper.native_getObject();

// ... do smth

// 2: return an object back to native code
Object result = jni_wrapper.native_doSmthWithObject(obj);

因此,代码需要保存对对象的引用,并以某种方式找到它(在上面的示例中,在1:和2:之间)。我可以创建自己的类和特殊实例字段(如果需要的话)来保存引用。

我使用了下一个解决方案(只在Index对象的“指针”实例字段中保持指向实例的指针),但它似乎不起作用。

Java (Index.java):

代码语言:javascript
运行
复制
/**
 *  CXIndex
 */
public class Index {

    private long pointer;

    public long getPointer() {
        return pointer;
    }
}

本地代码:

代码语言:javascript
运行
复制
// index
static jclass IndexClass;
static jmethodID IndexConstructor;
static jfieldID IndexPointerField;

void bindIndex(JNIEnv *env)
{
    IndexClass = env->FindClass("name/antonsmirnov/xxx/dto/Index");
    IndexConstructor = env->GetMethodID(IndexClass, "<init>", "()V");
    IndexPointerField = env->GetFieldID(IndexClass, "pointer", "J");
}

// map CXIndex
jobject mapIndex(JNIEnv *env, CXIndex *index)
{
    if (IndexClass == NULL)
        bindIndex(env);


    jobject obj = env->NewObject(IndexClass, IndexConstructor);
    jlong jpointer = reinterpret_cast<jlong>(index);

    env->SetLongField(obj, IndexPointerField, jpointer);
    return obj;
}

// map Index -> CXIndex
CXIndex unmapIndex(JNIEnv *env, jobject jindex)
{
    if (IndexClass == NULL)
        bindIndex(env);

    jlong jpointer = env->GetLongField(jindex, IndexPointerField);
    CXIndex *ptr = reinterpret_cast<CXIndex*>(jpointer);
    return *ptr;
}

这涉及到Android,它可以带来特定的行为!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-04 14:40:37

您可以创建一个函数

代码语言:javascript
运行
复制
jlong JNI_mypackage_myclass_createMyNativePeer() {

      return new MyNativePeer();
}

然后,在Java中,将返回的值保留在类中。

代码语言:javascript
运行
复制
class MyWrapper {
    private long mPeer;

    public void createPeer() {
       mPeer = createMyNativePeer();
    }

   private native long createMyNativePeer();

   public void controlPeer(int param) {
            controlPeer(mPeer, param);
   }

   private native void controlPeer(long peer, int param);

}

然后将该值传递给您的控制函数:

代码语言:javascript
运行
复制
jvoid JNI_mypackage_myclass_controlPeer(jlong peer, int someParam) {
      ((*MyNativePeer)peer)->doSomething(param);
}
票数 1
EN

Stack Overflow用户

发布于 2017-06-20 04:12:15

这里至少有两个问题。

  1. 不能保存对jobjectjclass的静态引用。要做到这一点,需要一个GlobalRefWeakGlobalRef
  2. JNI代码中完全没有错误检查。必须检查GetClass()GetMethodID()GetFieldID()GetLongField()等的结果,也必须检查挂起的异常。

但是我不明白你为什么需要这个。第一个解决方案要简单得多,可以通过在公共Java方法中封装私有本机方法来实现,这些方法调用私有方法并自动提供所需的对象,其中对象可以存储在具有本机方法的类中。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19183849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档