Общие объекты, символы, связывание и загрузка C / C ++ lib - PullRequest
0 голосов
/ 02 сентября 2018

Фон

Я парень, который никогда не программировал с NDK . Никогда. Много лет назад я писал код на C и C ++, но тогда это было. В настоящее время я пишу Android-приложения полностью на Java, как и многие другие.

Примечание: Этот вопрос касается не Android, а общих общих объектов, связывания библиотек на C / C ++, генерации символов и тому подобного. Таким образом, вам не нужно Android ноу-хау, чтобы ответить на него.

Во-вторых, для всех вас, незнакомых с NDK, это просто средство для «общения» с родными библиотеками C / C ++, представленными как общие объекты на Android (на основе Unix)


Проблема:

Теперь, пытаясь написать приложение для записи звонков в Android, пройдя 3 дня адского программирования, я нашел правду:

Просто невозможно написать полнофункциональный регистратор вызовов на Android с использованием стандартных API-интерфейсов Java, если вы не готовы испачкать руки JNI, NDK, C / C ++ и т. Д.

И то, что я сделал ... со вчерашнего вечера. Переходя к части кода C / C ++, есть еще одна вещь, которую другие приложения сделали для успешной записи вызовов: используйте libmedia.so (, которая является библиотекой, специфичной для поставщика, которую можно найти на большинстве Android устройства на рынке для доступа к некоторым медиа функциям ). Если это не найдено, тогда хорошо ... Я не понимаю, что этот парень сделал:

int load(JNIEnv *env, jobject this) {
    void *handleLibMedia;
    void *handleLibUtils;
    int result = -1;
    lspr func = NULL;

//    pthread_t newthread = (pthread_t) thiz;
    pthread_t newthread = (pthread_t) thiz;

    handleLibMedia = dlopen("libmedia.so", RTLD_NOW | RTLD_GLOBAL);
    if (handleLibMedia != NULL) {
        func = dlsym(handleLibMedia, "_ZN7android11AudioSystem13setParametersEiRKNS_7String8E");
        if (func != NULL) {
//            result = func(env, thiz);
            result = 0;
        }
        audioSetParameters = (lasp) func;
    } else {
        result = -1;
    }

    handleLibUtils = dlopen("libutils.so", RTLD_NOW | RTLD_GLOBAL);
    if (handleLibUtils != NULL) {
        fstr = dlsym(handleLibUtils, "_ZN7android7String8C2EPKc");
        if (fstr == NULL) {
            result = -1;
        }
    } else {
        result = -1;
    }

    cmd = CM_D;

    int resultTh = pthread_create(&newthread, NULL, taskAudioSetParam, NULL);

//    dlclose(handleLibMedia);
//    dlclose(handleLibUtils);

    return result;
}

Проходя через это, я получил грубое представление о том, что он проверяет библиотеку с именем libmedia.so и, если он не может ее найти, он пытается найти функцию с именем dlsym():

func = dlsym(handleLibMedia, "_ZN7android11AudioSystem13setParametersEiRKNS_7String8E");

Вы можете увидеть Страшно Строка "_ZN7android11AudioSystem13setParametersEiRKNS_7String8E" Вы также можете найти это в Android-приложении VLC Player:

https://github.com/mstorsjo/vlc-android/blob/master/android-libs/libmedia.symbols

Вопросы:

  • Что такое строка / символ "_ZN7android11AudioSystem13setParametersEiRKNS_7String8E"?
  • Что это за pthread_t?
  • Как мне понять JNI? или каковы минимумы и предостережения, которые я должен знать при программировании на JNI, чтобы иметь возможность кодировать без выстрелов в ногу?

1 Ответ

0 голосов
/ 02 сентября 2018

_ZN7android11AudioSystem13setParametersEiRKNS_7String8E - это искаженное имя для функции

android::AudioSystem::setParameters(int, android::String8 const&)

Библиотека libmedia, по-видимому, написана на C ++, поэтому имена ее функций искажены. Обычно вы позволяете компилятору иметь дело со вставкой кода для динамического связывания с этой библиотекой, но если вы хотите избежать жесткой зависимости от нее и загружать ее во время выполнения, вам потребуется использовать искаженные имена для загрузки символов из нее.

Быстрый Google не показал никакой документации для этой функции, но я нашел какой-то старый исходный код . Однако обратите внимание, что этот файл ушел из текущей главной ветви этого хранилища.


pthread_t - это тип, используемый библиотекой потоков POSIX для хранения идентификаторов потоков. Почему newthread инициализируется значением thiz Понятия не имею. Более поздний вызов pthread_create перезаписывает это значение, и эта переменная никогда ранее не используется в качестве параметра для закомментированного вызова AutioSystem::setParameters.


Что касается вашего третьего вопроса, это очень широкая тема. Не рекомендуется загружать недокументированные внутренние библиотеки.

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