jni回调适用于java类型,但不适用于c类型

时间:2011-06-20 13:23:26

标签: c callback java-native-interface swig

我遵循了建议 registering java function as a callback in C function并且可以使用“简单”类型回调,例如整数和字符串,例如:

jstring js = (*env)->NewStringUTF(env, "hello");
(*env)->CallStaticVoidMethod(env, cls, methodid, js);

但是,如果我尝试对使用SWIG包装的C数据类型执行相同的操作,我只会在Java中获取空指针。在C部分,他们肯定不是0.他们需要区别对待吗?

[编辑:] 更多信息:

如上所述,char * / string也适用于我。我正在寻找一个C struct的解决方案,它已经被SWIG包装并且已经用Java分配。

E.g:

typedef struct {
    unsigned short length;
    unsigned short value;
} lv_t;

正在被SWIG包装,所以我可以在Java中使用它:

lv_t lv;
lv = modulename.modulename_new_lv();
lv.setLength(1);
lv.setValue(2);

然后我将这个结构从Java提供给C:

modulename.send(lv);

C将通过网络发送,接收一些回复并更改lv中的值。现在,这应该将修改后的lv返回给Java。

void jni_call_received_hook(lv_t* lv){
   JNIEnv* m_env;
   (*m_vm)->AttachCurrentThread(m_vm, (void**) &m_env, NULL );
   jclass cls = (*m_env)->FindClass( m_env, "gui/StateMachine" );
   jmethodID mid = (*m_env)->GetStaticMethodID(m_env, cls, "callReceivedEvent", "(Lcom/something/modulename/jni/lv_t;)V");
   if (mid == 0){
      log(E, "Unable to find method for callback");
      return;
   }

   // what to do here to create a jobject?
   jobject lv_j = ...;

   (*m_env)->CallStaticVoidMethod(m_env, cls, mid, lv_j);

}

哪个电话:

public static void messageHandler(lv_t lv) {
    System.out.println("messageHandler().");
    System.out.println("lv " + lv);
}

1 个答案:

答案 0 :(得分:2)

很抱歉,但我还没有对您的问题发表评论,所以这更多是评论而不是答案。无论如何,我最近做过类似的事情。

我的回调有效并且实现为:

void jni_call_received_hook(char* username){
 JNIEnv* m_env;
 (*m_vm)->AttachCurrentThread(m_vm, (void**) &m_env, NULL );
 jclass cls = (*m_env)->FindClass( m_env, "gui/StateMachine" );
 jmethodID mid = (*m_env)->GetStaticMethodID(m_env, cls, "callReceivedEvent", "(Ljava/lang/String;)V");
 if (mid == 0){
   log(E, "Unable to find method for callback");
   return;
 }
 (*m_env)->CallStaticVoidMethod(m_env, cls, mid, (*m_env)->NewStringUTF(m_env, username));
}

变量m_vm是我在调用注册此回调的方法时保留的JVM实例,如下所示:

JNIEXPORT void JNICALL Java_gui_StateMachine_setCallReceivedCallback(JNIEnv *e, jobject o){
 (*e)->GetJavaVM(e, &m_vm );
 set_call_received_hook(jni_call_received_hook);
}

也许你错过了什么。如果这还不够清楚,请告诉我。希望它有所帮助。