共享对象,符号,C / C ++ lib链接和加载

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了共享对象,符号,C / C ++ lib链接和加载相关的知识,希望对你有一定的参考价值。

背景

我是一个从未用NDK编程的人。决不。几年前,我曾经用C和C ++编写代码,但当时就是这样。目前,我正在像许多其他人一样专门用Java编写android应用程序。

注意:这个问题不是关于Android,而是关于共享对象,链接C / C ++中的库,符号生成等。因此,您不需要Android专有技术来回答它。

其次,对于所有不熟悉NDK的人来说,它只是一个“与”交谈的工具,这些库是作为Android上的共享对象(基于Unix)而存在的本地C / C ++库。


问题:

现在,在尝试在Android中编写一个呼叫记录器应用程序时,经过3天的编程地狱后,我发现了真相:

没有办法在Android上使用标准框架Java API编写功能齐全的Call记录器,除非你准备好了解一些JNI,NDK,C / C ++等等。

而且,从昨天晚上起,我做了...深入了解代码的C / C ++部分,其他应用程序为成功记录调用做了一件事:利用libmedia.so(这是市场上大多数Android设备上的供应商特定库)访问一些媒体功能)。如果没有找到,那么......我不明白this家伙做了什么:

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"你也可以在VLC播放器的Android应用程序中找到它:

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

问题:

  • 什么是字符串/符号"_ZN7android11AudioSystem13setParametersEiRKNS_7String8E"
  • 这是什么pthread_t?
  • 我如何快速了解JNI以了解这一点?或者在JNI编程时我必须知道的最低限度和警告是什么,以便能够在不用脚射击的情况下进行编码?
答案

_ZN7android11AudioSystem13setParametersEiRKNS_7String8E是该功能的mangled name

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

libmedia库显然是用C ++编写的,因此它的函数名称被破坏了。通常,您会让编译器处理插入代码以动态链接到该库,但是如果您想避免对它的硬依赖并在运行时加载它,那么您将需要使用损坏的名称从中加载符号。

一个快速谷歌没有透露该功能的任何文档,但我确实找到了一些旧的source code。但请注意,该文件已从该存储库的当前master branch中删除。


pthread_t是POSIX线程库用来保存线程ID的类型。为什么用newthread的值初始化thiz我不知道。后来对pthread_create的调用会覆盖该值,并且该变量在其他变量之前从未用作AutioSystem::setParameters注释掉的调用的参数。


关于你的第三个问题,这是一个非常广泛的话题。不加载未记录的内部库是一个很好的建议。

以上是关于共享对象,符号,C / C ++ lib链接和加载的主要内容,如果未能解决你的问题,请参考以下文章

erlang nif共享库上的未定义符号

两次加载共享库

在 Eclipse 中将 .so lib 添加到 .pro 文件中。 C++/Eclipse/Linux

编译共享库时出现链接错误

链接器找不到与 Libunbound 的共享对象

C温故补缺(十七):动态链接(ELF,PIC,GOT,PLT)