2011-07-19 10 views
13

Necesito implementar la función de devolución de llamada en Java usando "interfaz". He escrito la parte de la aplicación como MyJavaFunction(int size, m_GetSizeInterface);Implementar la función de devolución de llamada en JNI usando la interfaz

m_GetSizeInterface es una interfaz que contiene la función de devolución de llamada GetSize. Este método GetSize es anulado en la aplicación. En JNI necesito llamar a una función CPP que tenga el prototipo int MyCPPFunction(int size, int (*callback)(int* ID));

¿Cómo puedo pasar este GetSize como parámetro a MyCPPFunction en JNI? Por favor, ayuda

public int GetSize (m_SizeClass arg0) 
{ 
    g_size = arg0.size; 
     return 0; 
} 

Respuesta

15

La complicación aquí es que desea invocar código nativo C++ que, a su vez, desea invocar un método Java. Esto es realmente un poco complicado.

Necesita crear una función JNI C++ para llamar a java, y una función C++ que coincida con la firma de devolución de llamada MyCPPFunction. Este último actuará como un contenedor para llamar al método java.

Debido a que la envoltura se necesita información sobre el entorno JNI, que no puede ser proporcionada por los parámetros (para que no arruinar la firma) se crea un par de variables globales para sostenerlo:

jobject g_getSizeIface; 
jmethodID g_method; 
JNIEnv *g_env; 

La función de C++, que java se llame es la siguiente:

JNIEXPORT void JNICALL Java_ClassName_MyCPPFunction 
    (JNIEnv *env, jint size, jobject getSizeInterface) 
{ 
     jclass objclass = env->GetObjectClass(getSizeInterface); 
     jmethodID method = env->GetMethodID(objclass, "GetSize", "(m_SizeClass)I"); 
     if(methodID == 0){ 
      cout << "could not get method id!\n"; 
      return; 
     } 
     g_method = method; 
     g_getSizeIface = getSizeInterface; 
     g_env = env 
     MyCPPFunction(size, WrapperFunc); 
} 

Y la función de contenedor es así:

int WrapperFunc(int *id) 
{ 
     jint retval; 
     //marshalling an int* to a m_SizeClass boogy-woogy. 
     ... 
     g_env->ExceptionClear(); 
     retval = g_env->CallIntMethod(g_getSizeIface, g_method, 
            /*marshalled m_SizeClass*/); 
     if(g_env->ExceptionOccured()){ 
      //panic! Light fires! The British are coming!!! 
      ... 
      g_env->ExceptionClear(); 
     }  
     return rvalue; 
} 
+0

podemos tener code..what muestra funcional completa será la declaración en la capa de Java? – CoDe

+0

¿Qué sucede si se necesita registrar la devolución de llamada con código nativo varias veces (pasando diferentes implementaciones de interfaz), de modo que cada registro de WrapperFunc tenga un objeto/método de interfaz asociado para invocar – xorcus

0
#include <functional> 
#include <cstdlib> 
#include <map> 

class SimpleQueueEvent { 

public: 

    SimpleQueueEvent(){}; 
    ~SimpleQueueEvent(){}; 

    //for C++ code call 
    int queueEvent(std::function<void(void)> func){ 
     int curTime = time(0) + rand() % 10000; 
     eventMaps.insert(std::map<int, std::function<void(void)>>::value_type(curTime, func)); 
     return curTime; 

     //Call Java method to invoke method, such as 
     //env->FindClass("...."); 
     //jmethodID method = env->FindMethod("onPostQueueEvent"...); 
     //env->InvokeVoidMethod(); 

     //Java code like this.. 
     // private void onPostQueueEvent(final int eventId){ 
     // listener.PostQueueEvent(new Runnable() { 
     // public void run() { 
     //  nativeEventFunc(eventId); 
     // } 
     // }); 
     // private static native void nativeEventFunc(int eventId); 

    } 

    void nativeEventFunc(int eventId){ 
     if(eventMaps.find(eventId) != eventMaps.end()){ 
      std::function<void(void)> func = eventMaps.at(eventId); 
      func(); 
     } 
    } 



private: 
    std::map<int, std::function<void(void)>> eventMaps; 


}; 

// y la prueba de código es:

SimpleQueueEvent queueEvent; 
    std::function<void(void)> func = [](){ 
     printf("native runnable..\n"); 
    }; 

    int evenId = queueEvent.queueEvent(func); 
    queueEvent.nativeEventFunc(evenId); 
Cuestiones relacionadas