我们可以将为 Linux 编译的“.so”库用于 android 吗?
Can we use ".so" library compiled for Linux into android?
我正在为 C++“.so”编写包装器 class。我想使用 JNI 在 Java 应用程序和 Android 应用程序中使用该库。所以我必须创建将执行 JNI 调用的头文件和 cpp 文件。
我可以在 Java 应用程序中的 Linux 上使用它。
我遵循的步骤:
创建了 java class 并在 class
中调用了本地函数
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 class 并生成 "native.so"
这工作正常。当从 TestWrapper.java 调用时,"native.so" 可以调用函数形式 "ibCppTobeUsed.so.0"。
我也想为 android 使用相同的库。所以,我必须在 Android NDK 中重新编写包装器 class 吗?或者我可以为 Android 平台编译我的 "native.so"?
如果我尝试直接使用它,我会收到错误
"install_failed_no_matching_abis".
不,不能使用同一个共享库。 Android 不是 GNU。您需要为 Android.
编译您的库
So, I have to write wrapper class all over again in Android NDK?
不,您可以用对两者都适用的方式来编写它。您需要从 main
class 中分解出我们的 JNI 包装器 class,因为 Android 使用 Activity
而不是 main
.
我也会强烈建议不要在任何平台上依赖dlclose
。 API 不合理,会导致现代 C++ 出现令人惊讶的行为。带有 non-trivial 析构函数的单个全局 thread_local
呈现库 un-unloadable,因此下一个 dlopen
不会像您预期的那样重置库状态。如果您需要为您的库实现 initialization/finalization 逻辑,请将显式 Initialize
和 Finalize
函数作为库的一部分并直接调用它们。
在不了解您的体系结构的完整体系结构的情况下,我无法确定,但是根据您在此处提供的示例,我建议您完全且仅从 JNI 中删除 dlopen
/dlsym
link 直接对抗 libCppTobeUsed
。
我正在为 C++“.so”编写包装器 class。我想使用 JNI 在 Java 应用程序和 Android 应用程序中使用该库。所以我必须创建将执行 JNI 调用的头文件和 cpp 文件。 我可以在 Java 应用程序中的 Linux 上使用它。
我遵循的步骤:
创建了 java class 并在 class
中调用了本地函数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 class 并生成 "native.so"
这工作正常。当从 TestWrapper.java 调用时,"native.so" 可以调用函数形式 "ibCppTobeUsed.so.0"。
我也想为 android 使用相同的库。所以,我必须在 Android NDK 中重新编写包装器 class 吗?或者我可以为 Android 平台编译我的 "native.so"?
如果我尝试直接使用它,我会收到错误
"install_failed_no_matching_abis".
不,不能使用同一个共享库。 Android 不是 GNU。您需要为 Android.
编译您的库So, I have to write wrapper class all over again in Android NDK?
不,您可以用对两者都适用的方式来编写它。您需要从 main
class 中分解出我们的 JNI 包装器 class,因为 Android 使用 Activity
而不是 main
.
我也会强烈建议不要在任何平台上依赖dlclose
。 API 不合理,会导致现代 C++ 出现令人惊讶的行为。带有 non-trivial 析构函数的单个全局 thread_local
呈现库 un-unloadable,因此下一个 dlopen
不会像您预期的那样重置库状态。如果您需要为您的库实现 initialization/finalization 逻辑,请将显式 Initialize
和 Finalize
函数作为库的一部分并直接调用它们。
在不了解您的体系结构的完整体系结构的情况下,我无法确定,但是根据您在此处提供的示例,我建议您完全且仅从 JNI 中删除 dlopen
/dlsym
link 直接对抗 libCppTobeUsed
。