2011-06-20 2 views
1

j'ai suivi les conseils à registering java function as a callback in C function et peut callback avec des types « simples » comme entier et chaîne, par exemple:rappel JNI fonctionne pour les types de java, mais pas les types de c

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

Cependant, si je suis En essayant de faire la même chose avec les types de données C qui ont été enveloppés avec SWIG, je ne reçois que des pointeurs NULL en Java. Dans la partie C, ils ne sont certainement pas 0. Doivent-ils être traités différemment?

[EDIT:] Quelques informations supplémentaires:

Comme indiqué ci-dessus, char */string travaille pour moi aussi. Je suis à la recherche d'une solution pour C struct, qui a été enveloppée par SWIG et qui a été allouée en Java.

Par exemple:

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

devient enveloppées par SWIG, donc je peux l'utiliser en Java:

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

Alors je donnerai ce struct de Java à C:

modulename.send(lv); 

C l'enverra sur le réseau, recevra une réponse et changera les valeurs en lv. Maintenant, cela devrait ramener le lv modifié à 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); 

}

Quels sont les appels:

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

Répondre

2

Désolé mais je ne suis pas en mesure de commenter votre question encore, si cela est plus un commentaire plutôt qu'une réponse. Quoi qu'il en soit, j'ai récemment fait quelque chose comme ça.

Mon rappel fonctionne et est mis en œuvre:

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

La m_vm variable est une instance de la machine virtuelle Java que j'ai gardé à appeler une méthode qui a enregistré ce rappel, comme ceci:

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

Peut-être votre quelque chose qui manque. Faites-moi savoir si ce n'est pas assez clair. J'espère que cela aide.

+0

Plus de détails sur C struct et call chain. – mab

+0

génial, meilleur exemple de rappel à ce jour – Houston

Questions connexes