当前位置: 首页 > 面试题库 >

使用接口在JNI中实现回调函数

荀豪
2023-03-14
问题内容

我需要使用“接口”在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;
}

问题答案:

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

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

因为包装器将需要有关JNI环境的信息,而这些信息不能由参数提供(否则我们将破坏签名),因此您将创建一些全局变量来保存它:

jobject g_getSizeIface;
jmethodID g_method;
JNIEnv *g_env;

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

因此包装函数是:

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


 类似资料:
  • 问题内容: 我想包装这样的javascript代码: 这是我如何用Java编写它: 但这不起作用。即使您在我的浏览器控制台中也没有任何错误。有人知道如何使它适用于外部回调函数吗?感谢致敬。 问题答案: 我终于找到了解决方案。看来我的Java代码与我的JavaScript代码不一致。感谢Colin Alworth为我指出了不一致的部分。所以这是我的完整代码: 现在,每当我运行它时,都会正确调用外部函

  • 我传递给Builder的lambda被填充到对象中,并定期(每小时)调用以刷新其他成员。它第一次被成功调用。我不确定lambda是否保留了,来合法地调用反向JNI函数? 我好像收到了11号信号错误,西格夫。这种分段错误是否可以以任何方式捕获,这样应用程序就不会崩溃? 它似乎在-

  • 问题内容: 我习惯于使用类似JavaScript或类似Erlang的语言编写代码,在其中我可以轻松实现回调函数。现在,我必须用Java编写一些东西。我想出了如何执行这样的回调: 问题是:这是正确的方法吗? 问题答案: 像这样简单地将一个接口(回调实现)传递给您的可运行对象 和一切简单的教程,您需要了解线程 这里

  • 情境:我有一个实现了JNI的dll,我想从一个Cpp应用程序调用其中的方法。 当前状态:根据我的理解,一个实现了JNI的dll实际上与JAVA无关,例如:在test.JAVA中,我编写了 并在testdll.cp 我认为这样的程序与JVM无关,jint结构似乎已经在JNI.h中完全定义了。 因此,我想知道是否可以直接调用而不从Cpp应用程序创建VM,如果可以,请: 参数列表中的`jnienv*`和

  • 我有一个接口,它的函数当前返回它自己。但是,我希望任何实现类都返回该类,而不是基接口。例如,在这个简化的示例中,它工作得很好: 这显然是失败的,因为重写函数不再与接口中的声明匹配。 我需要baz()返回Class而不是Interface,因为调用者可以以任意顺序调用bar和baz任意次数,但是目前所有bar()调用必须在所有baz()调用之前,除非我们重复地向下调用。 更复杂的是foo()函数,它

  • 我正在用JNI异步执行测试Rust。我想在Rust中执行请求,并用回调将结果异步返回到Android。我正在测试代码来执行命令行中的请求,它工作得很好。 这就是它在命令行上的工作方式: null null 我正在检查它是如何工作的,但示例似乎已经过时:*https://github.com/mozilla/rust-android-gradle/blob/master/samples/rust/s