开发者

jni callback works for java types, but not c types

开发者 https://www.devze.com 2023-03-13 23:15 出处:网络
I have followed the advice at registering java function as a callback in C function and can callback with \"simple\" types such as integer and string, e.g.:

I have followed the advice at registering java function as a callback in C function and can callback with "simple" types such as integer and string, e.g.:

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

However, if I am trying to do the same with C datatypes which have been wrapped with SWIG, I am only getting null pointers in Java. In the C part they are definitely not 0. Do they need to be treated differently?

[EDIT:] Some more informatio开发者_如何转开发n:

As stated above, char*/string is working for me as well. I am looking for a solution for C struct's, which have been wrapped by SWIG and have been allocated in Java.

E.g.:

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

is getting wrapped by SWIG, so I can use it in Java:

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

Then I will give this struct from Java to C:

modulename.send(lv);

C will send it over the network, receive some reply and change the values in lv. Now, this should give the modified lv back to 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);

}

Which calls:

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


Sorry but I'm not able to comment in your question yet, so this is more a comment rather than an answer. Anyway, I've recently done something like that.

My callback works and is implemented as:

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

The variable m_vm is an instance of the JVM I've kept upon calling a method that registered this callback, like this:

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

Maybe your missing something. Let me know if this isn't clear enough. Hope it helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消