共享对象,符号,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链接和加载的主要内容,如果未能解决你的问题,请参考以下文章