我们可以将为 Linux 编译的“.so”库用于 android 吗?

Can we use ".so" library compiled for Linux into android?

我正在为 C++“.so”编写包装器 class。我想使用 JNI 在 Java 应用程序和 Android 应用程序中使用该库。所以我必须创建将执行 JNI 调用的头文件和 cpp 文件。 我可以在 Java 应用程序中的 Linux 上使用它。

我遵循的步骤:

  1. 创建了 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();
    }
    
  2. 已创建头文件和 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;
      }
        }
    }
    
  3. 编译此 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 逻辑,请将显式 InitializeFinalize 函数作为库的一部分并直接调用它们。

在不了解您的体系结构的完整体系结构的情况下,我无法确定,但是根据您在此处提供的示例,我建议您完全且仅从 JNI 中删除 dlopen/dlsym link 直接对抗 libCppTobeUsed