我正在为C ++“ .so”编写包装类。我想在使用JNI的Java应用程序和Android应用程序中使用该库。因此,我必须创建将执行JNI调用的头文件和cpp文件。 我可以在Linux上的Java应用程序中使用它。
我遵循的步骤:
创建了Java类,并在该类中调用了本机函数
public class TestWrapper {
static {
System.load("/home/native.so");
}
public static void main(String[] args) {
new TestWrapper().TestWrapper();
}
private native void sayHello();
}
已创建头文件和cpp文件。 CCP包含以下代码
JNIEXPORT void JNICALL Java_TestWrapper_sayHello(JNIEnv *, jobject){
uint16_t data = 0;
void (*func_print_name)(const uint16_t*);
void* handle = dlopen("libCppTobeUsed.so.0", RTLD_LAZY);
if (handle){
*(void**)(&func_print_name) = dlsym(handle, function_name);
func_print_name(&data);
dlclose(handle);
std::cout << "data received .." << data << std::endl;
}
}
}
编译此 cpp 类并生成“ native.so”
这很好。从TestWrapper.java中调用时,“ native.so”可以调用函数形式“ ibCppTobeUsed.so.0”。
我也想为Android使用相同的库。因此,我必须在Android NDK中重新编写包装器类吗?或者我可以为Android平台编译“ native.so”?
如果我尝试直接使用它,则会出现错误
“ install_failed_no_matching_abis”。
答案 0 :(得分:0)
否,您不能使用相同的共享库。 Android不是GNU。您需要为Android编译库。
那么,我必须在Android NDK中重新编写包装器类吗?
否,您可以采用两种方式都可以编写的方式。您需要从main
类中考虑我们的JNI包装器类,因为Android使用Activity
而不是main
。
我也强烈建议不要在任何平台上都依赖dlclose
。该API不健全,并且会导致现代C ++出现令人惊讶的行为。具有非平凡析构函数的单个全局thread_local
会使库无法卸载,因此下一个dlopen
不会像您期望的那样重置库状态。如果您需要为库实现初始化/完成逻辑,请将显式Initialize
和Finalize
函数作为库的一部分,然后直接调用它们。
我不确定自己的体系结构是完整的体系结构,但是从这里给出的示例中,我建议完全从JNI中删除dlopen
/ dlsym
,然后直接链接直接libCppTobeUsed
。