我想在Android工作室中使用三个C ++文件。
我已将它们编译成静态库。现在我想围绕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 image\n" );
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)?
答案 0 :(得分:0)
您可以将包装函数放在任何将被编译的文件中,无论是新的还是现有的。与Java不同,在C ++中,文件名对编译器没有意义。
如果您不打算独立于Java调用它们,则不需要包装其他方法。
PS:请注意,包装函数的名称Java_cgi_pi_detect
派生自定义此detect
本机方法的Java类。使用javah
工具生成实现本机Java方法的C函数的正确名称。
答案 1 :(得分:0)
这样调用main()
充满了危险。 将要调用哪个 main()
? JVM可执行文件也有main()
。 (是的,我忽略了“未定义的行为”,因为问题是关于如何使其发挥作用。)
获取所需main()
的困难方法是将其编译为共享对象,加载该共享对象,并使用{{3自行查找该共享对象中的main()
运行时动态链接}和dlopen()
(省略错误检查):
#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库需要使用libdl.so
链接器参数与-ldl
的依赖关联。
简单方法?
将要调用的main()
重命名为其他内容并将其放入普通的JNI共享对象中。然后只需调用它 - 它不再被称为main()
,因此不再存在任何名称冲突。
尽管如此,我怀疑你仍然可能会遇到问题 - 立即想到名称冲突或不兼容的库。
的更简单方法是什么?
在子进程中运行它,因为它是设计运行的方式,无论如何它实际上是一个黑盒子:你用参数调用它,它做它做的任何事情,你得到一个int
返回值。对于函数调用或子进程来说,这是相同的。