pnk
pnk

Reputation: 35

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

I am writing a wrapper class for C++ ".so". I want to use the library in Java application and Android app using JNI. So I have to create header file and cpp file which will do JNI calls. I could use that on Linux in Java application.

The steps I followed:

  1. Created java class and called native functions in that class

    public class TestWrapper { 
        static {
            System.load("/home/native.so");    
    }         
        public static void main(String[] args) {
            new TestWrapper().TestWrapper();    
    } 
        private native void sayHello();
    }
    
  2. Created header file and cpp file. CCP contains following code

    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. Compiled this cpp class and generated "native.so"

This is working fine. The "native.so" could call the fuction form "ibCppTobeUsed.so.0" when called from TestWrapper.java.

I want to use same library for android as well. So, I have to write wrapper class all over again in Android NDK? Or I can compile my "native.so" for Android platform?

If I try to use it directly, I get error

"install_failed_no_matching_abis".

Upvotes: 0

Views: 1662

Answers (1)

Dan Albert
Dan Albert

Reputation: 10509

No, you cannot use the same shared library. Android is not GNU. You need to compile your libraries for Android.

So, I have to write wrapper class all over again in Android NDK?

No, you can write it in a way that works for both. You need to factor our your JNI wrapper class from your main class, since Android uses Activity instead of main.

I would also strongly recommend against ever relying on dlclose on any platform. The API is not sound, and will lead to surprising behavior with modern C++. A single global thread_local with a non-trivial destructor renders the library un-unloadable, so the next dlopen will not reset library state as you might expect. If you need to implement initialization/finalization logic for your library, make explicit Initialize and Finalize functions a part of the libary and call them directly.

Without knowing your architecture's full architecture I can't be sure, but from the sample you've given here I'd recommend dropping the dlopen/dlsym from your JNI entirely and just link against libCppTobeUsed directly.

Upvotes: 2

Related Questions