围绕C++方法编写一个JNI包装器

Write a JNI wrapper around a C++ method

本文关键字:一个 JNI 包装 方法 C++ 围绕      更新时间:2023-10-16

我有三个C++文件,我想在Android工作室中使用。

  • 页眉.h
  • A.cpp(包含主方法+其他方法)
  • B.cpp

我已将它们编译成一个静态库。现在,我想围绕C++方法编写JNI包装器,并将其调用到java部分。到目前为止,这是我的包装:

#include <jni.h>
#include <string.h>
#include <stdlib.h>
extern "C" {

   JNIEXPORT int JNICALL Java_cgi_pi_detect(? ,?) {
   IplImage * byteQueryImage = loadByteImage ( ? );
  if ( !byteQueryImage )
  {
    printf ( "couldn't load query imagen" );
    return -1;
  }
  // Detect text in the image
  IplImage * output = textDetection ( byteQueryImage, atoi(1));
  cvReleaseImage ( &byteQueryImage );
  cvSaveImage ( ? , output );
  cvReleaseImage ( &output );
  return 0;
}
}

我想给它两张图片作为参数:一张加载IplImage * byteQueryImage = loadByteImage ( ? );,另一张保存cvSaveImage ( ? , output );。这两个参数的jni类型JNIEXPORT int JNICALL Java_cgi_pi_detect(? ,?)应该是什么(如果我认为图片是.png)?

这样调用main()充满了危险将调用哪个main()?JVM可执行文件还有一个main()。(是的,我忽略了"未定义的行为",因为问题是如何使其发挥作用。)

要获得所需的main(),最困难的方法是将其编译成一个共享对象,加载该共享对象,并通过使用dlopen()dlsym()的运行时动态链接在该共享对象中自己找到main()(省略错误检查):

#include <dlfcn.h>
...
// use a typedef for the function pointer
typedef int ( *main_func_t )( int, char ** );
...
// Handle to your .so with your "main()" in it
// make them static so they're only loaded once
static void *libHandle = NULL;
static main_func_t libMain = NULL;
if ( NULL == libHandle )
{
    libHandle = dlopen( "yourLibName.so", RTLD_NOW );
    libMain = ( main_func_t ) dlsym( libHandle, "main" );
}
...
// now call the main() in that library
int mainRetVal = libMain( argc, argv );
...

因此,这意味着您需要两个共享对象:第一个"普通"对象用于保存您的JNI调用,第二个对象用于保存要调用的"main()"。第一个"普通"JNI库需要使用-ldl链接器参数与libdl.so的依赖项进行链接。

简单的方法?

将要调用的main()重命名为其他对象,并将其放入普通的JNI共享对象中。然后直接调用它——它不再被称为main(),因此不再有任何名称冲突。

即便如此,我怀疑您仍然可能遇到问题——名称冲突或不兼容的库会立即出现在脑海中。

是否更容易工作?

在子流程中运行它,因为这是它的运行方式,而且它实际上是一个黑盒:你用参数调用它,它做任何事情,然后你得到一个int返回值。函数调用或子流程也是如此。

您可以将包装函数放在任何将要编译的文件中,无论是新文件还是现有文件。与Java不同,在C++中,文件名对编译器没有任何意义。

如果您不打算独立于Java调用其他方法,则不需要包装它们。

PS:请注意,包装器函数的名称Java_cgi_pi_detect源自定义此detect本机方法的Java类。使用javah工具生成实现本机Java方法的C函数的正确名称。