且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2021-11-13 02:06:31

想要调用本地C ++代码,而你又要调用一个java方法。这实际上有点棘手。

The complication here is that you want to invoke native C++ code which you, in turn, want to invoke a java method. This is actually a bit tricky.

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

You need to create a JNI C++ function for java to call, and a C++ function matching the MyCPPFunction callback signature. The latter will act as a wrapper to call the java method.

因为包装器将需要关于JNI环境的信息,这不能由参数提供(为了破坏签名),你创建一些全局变量来保存它: / p>

Because the wrapper will need information about the JNI environment, which cannot be provided by parameters (lest we ruin the signature) you create a few global variables to hold it:

jobject g_getSizeIface;
jmethodID g_method;
JNIEnv *g_env;

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

The C++ function which java will call is the following:

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

而且包装函数是:

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