JNI обратный вызов работает для Java-типов, но не C-типов - PullRequest
1 голос
/ 20 июня 2011

Я следовал совету на регистрации java-функции в качестве обратного вызова в функции C и может вызывать обратные вызовы с «простыми» типами, такими как integer и string, например:

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

, если я пытаюсь сделать то же самое с типами данных C, которые были упакованы с SWIG, я получаю только нулевые указатели в Java.В части C они определенно не равны 0. Нужно ли обращаться с ними по-другому?

[EDIT:] Еще немного информации:

Как указано выше, char * / string работает для менятакже.Я ищу решение для структур C, которые были упакованы SWIG и размещены в Java.

Например:

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 Ответ

2 голосов
/ 20 июня 2011

Извините, но я пока не могу комментировать ваш вопрос, так что это скорее комментарий, чем ответ.Во всяком случае, я недавно сделал что-то подобное.

Мой обратный вызов работает и реализован как:

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

Возможно, вы что-то упустили.Дайте мне знать, если это не достаточно ясно.Надеюсь, это поможет.

...