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

时间:2019-07-03 06:08:27

标签: java android android-ndk

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

我遵循的步骤:

  1. 创建了Java类,并在该类中调用了本机函数

    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 类并生成“ native.so”

这很好。从TestWrapper.java中调用时,“ native.so”可以调用函数形式“ ibCppTobeUsed.so.0”。

我也想为Android使用相同的库。因此,我必须在Android NDK中重新编写包装器类吗?或者我可以为Android平台编译“ native.so”?

如果我尝试直接使用它,则会出现错误

  

“ install_failed_no_matching_abis”。

1 个答案:

答案 0 :(得分:0)

否,您不能使用相同的共享库。 Android不是GNU。您需要为Android编译库。

  

那么,我必须在Android NDK中重新编写包装器类吗?

否,您可以采用两种方式都可以编写的方式。您需要从main类中考虑我们的JNI包装器类,因为Android使用Activity而不是main

我也强烈建议不要在任何平台上都依赖dlclose。该API不健全,并且会导致现代C ++出现令人惊讶的行为。具有非平凡析构函数的单个全局thread_local会使库无法卸载,因此下一个dlopen不会像您期望的那样重置库状态。如果您需要为库实现初始化/完成逻辑,请将显式InitializeFinalize函数作为库的一部分,然后直接调用它们。

我不确定自己的体系结构是完整的体系结构,但是从这里给出的示例中,我建议完全从JNI中删除dlopen / dlsym,然后直接链接直接libCppTobeUsed