2013-10-04 51 views
0

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

// 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):

/** 
* CXIndex 
*/ 
public class Index { 

    private long pointer; 

    public long getPointer() { 
     return pointer; 
    } 
} 

本地代码:

// 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能带来哪些具体的行为!

+0

PS。根据http://developer.android.com/training/articles/perf-jni.html – 4ntoine

+0

[标签:编译器构造]与它完全无关,我也不确定持有静态引用是个好主意。 – EJP

回答

0

您可以创建一个功能

jlong JNI_mypackage_myclass_createMyNativePeer() { 

     return new MyNativePeer(); 
} 

然后在Java中你保持返回值类。

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); 

} 

然后你说值传递给你的控制功能:

jvoid JNI_mypackage_myclass_controlPeer(jlong peer, int someParam) { 
     ((*MyNativePeer)peer)->doSomething(param); 
} 
+0

只是持有var指针似乎不工作,因为在调用返回结果或smth后释放内存..应用程序崩溃时尝试使用从Java指针传递。 – 4ntoine

+0

我看过使用env-> NewGlobalRef,但它只涉及到jobject实例,我需要持有我的班级 – 4ntoine

+0

应该像 –

1

这里有至少两个问题。

  1. 您不能持有对jobjectjclass的静态引用。你需要一个GlobalRefWeakGlobalRef来做到这一点。
  2. 在您的JNI代码中完全没有错误检查。 GetClass(),GetMethodID(),GetFieldID(),GetLongField()等的结果必须全部检查并且还检查暂挂异常。

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

相关问题