Можем ли мы использовать библиотеку ".so", скомпилированную для Linux в Android? - PullRequest
0 голосов
/ 03 июля 2019

Я пишу класс-оболочку для C ++ ".so".Я хочу использовать библиотеку в Java-приложении и Android-приложении, используя JNI.Поэтому я должен создать заголовочный файл и файл cpp, которые будут выполнять вызовы JNI.Я мог бы использовать это в 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"

Этоработает нормально.«Native.so» может вызывать функциональную форму «ibCppTobeUsed.so.0» при вызове из TestWrapper.java.

Я хочу использовать ту же библиотеку и для Android.Итак, я должен снова написать класс оболочки в Android NDK?Или я могу скомпилировать свой "native.so" для платформы Android?

Если я пытаюсь использовать его напрямую, я получаю сообщение об ошибке

"install_failed_no_matching_abis".

1 Ответ

0 голосов
/ 03 июля 2019

Нет, вы не можете использовать одну и ту же общую библиотеку. Android не является GNU. Вам нужно скомпилировать свои библиотеки для Android.

Итак, мне снова нужно написать класс-оболочку в Android NDK?

Нет, вы можете написать это так, чтобы это работало для обоих. Вы должны отделить наш класс-оболочку JNI от класса main, поскольку Android использует Activity вместо main.

Я бы также настоятельно рекомендовал бы не полагаться на dlclose на любой платформе. API не является надежным и приведет к удивительному поведению с современным C ++. Один глобальный thread_local с нетривиальным деструктором делает библиотеку недоступной для выгрузки, поэтому следующий dlopen не сбросит состояние библиотеки, как вы могли бы ожидать. Если вам нужно реализовать логику инициализации / финализации для вашей библиотеки, сделайте явные функции Initialize и Finalize частью библиотеки и вызовите их напрямую.

Не зная полной архитектуры вашей архитектуры, я не могу быть уверен, но из приведенного вами примера я бы порекомендовал полностью удалить dlopen / dlsym из вашего JNI и просто ссылаться на libCppTobeUsed напрямую .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...