使用Interface在JNI中实现回调函数

ind*_*ira 16 java java-native-interface function-pointers interface callback

我需要使用"interface"在Java中实现回调函数.我已将应用程序部分编写为MyJavaFunction(int size, m_GetSizeInterface);

m_GetSizeInterface是一个包含回调函数GetSize的接口.此GetSize方法在应用程序中被覆盖.在JNI中,我需要调用具有原型的CPP函数int MyCPPFunction(int size, int (*callback)(int* ID));

如何将此GetSize作为参数传递给JNI中的MyCPPFunction?请帮忙

public int GetSize (m_SizeClass arg0)
{
    g_size = arg0.size;
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ave 17

这里的复杂之处在于您要调用本机C++代码,而您又需要调用java方法.这实际上有点棘手.

您需要为要调用的java创建一个JNI C++函数,以及一个与MyCPPFunction回调签名匹配的C++函数.后者将充当调用java方法的包装器.

因为包装器需要有关JNI环境的信息,这些信息不能通过参数提供(以免破坏签名),所以您需要创建一些全局变量来保存它:

jobject g_getSizeIface;
jmethodID g_method;
JNIEnv *g_env;
Run Code Online (Sandbox Code Playgroud)

java将调用的C++函数如下:

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){
          std::cout << "could not get method id!" << std::endl;
          return;
      }
      g_method = method;
      g_getSizeIface = getSizeInterface;
      g_env = env
      MyCPPFunction(size, WrapperFunc);
}
Run Code Online (Sandbox Code Playgroud)

因此包装函数是:

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->ExceptionOccurred()){
          //panic! Light fires! The British are coming!!!
          ...
          g_env->ExceptionClear();
      }     
      return rvalue;
}
Run Code Online (Sandbox Code Playgroud)