解决的需求

有些时候不能在NDK环境编译,或者使用NDK编译会颇费周折,然后又想使用Android系统自带的Log类方法,那么我们就可以使用dlopen来实现我们的目的。比如在OpenCV中添加Android的Log打印。

关于dlopen

  1. dlopen和dlclose对处理的lib进行引用计数,dlopen使引用计数加1,dlclose让引用计数减1,当对库的引用计数达到0的时候,才会把库unmap掉。
  2. dlsym返回查找到的第一个符合要求的函数地址,该地址指的是库加载进进程虚拟地址。
  3. 可以使用dlsym来实现对库的前一个函数的隐藏。There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find the first occurrence of the desired symbol using the default library search order. The latter will find the next occurrence of a function in the search order after the current library. This allows one to provide a wrapper around a function in another shared library.
  4. 在调用了dlclose之后,再使用dlsym得到的函数是不行的。虽然当使用dlclose使得引用计数为0之后,系统并不会立马把加载的库给unmap掉,但是这个时间是不确定的。也许在你调用dlclose之后,在系统unmap之前调用dlsym的函数,或者本次dlclose并没有让引用计数为0,比如进程中还有其他地方也dlopen同一个库,那么系统也不会unmap,这样调用dlsym的函数并不会出错。
  5. 如果你想dlopen一个库之后,需要在程序中一直使用这个库的函数,那么没有必要调用dlclose,包括在程序退出之前调用dlclose。因为程序退出会自动unmap这些库。但是如果你要dlopen很多库,可能会导致虚拟地址不足的情况,那么就需要调用dlclose以保证不会出错。https://stackoverflow.com/questions/26131102/is-it-safe-to-call-dlclose-after-dlsym

代码

使用如下代码,实现基于dlopen的Android Log方法调用

#include #include #define DLLOG_TAG  "Slender3d"static void logd( const char* format, ...){    #ifdef __aarch64__    const char libpath[] = "/system/lib64/liblog.so";#else    const char libpath[] = "/system/lib/liblog.so";#endif    const int ANDROID_LOG_DEBUG = 3;    using __android_log_printFunc = int(*)(int , const char* , const char* , ...);    static __android_log_printFunc slogFunc = NULL;    if(NULL == slogFunc){        void *handler = dlopen(libpath, RTLD_NOW | RTLD_LOCAL);        dlerror();        if (handler) {            const char *SYM = "__android_log_print";            slogFunc = reinterpret_cast<__android_log_printFunc>(dlsym(handler, SYM));            char *error;            if( (error = dlerror() != NULL){            slogFunc = NULL;                //LOGE("dlsym %s fail", libpath);            }        }        else {            //LOGE("dlopen %s fail", libpath);        }    }    if (slogFunc) {        va_list args;        va_start(args, format);        slogFunc(ANDROID_LOG_DEBUG, DLLOG_TAG, format, args);        va_end(args);    }    else {            //LOGE("dlsym %s fail", SYM);    }}

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 万字长文带你了解最常用的开源 Squid 代理服务器
  3. 收藏 Android系统 init 启动过程分析
  4. Android如何通过TextView实现超链接的跳转
  5. Android(安卓)通过读取本地Arp表获取当前局域网内其他设备信息
  6. DSL实战:仿Flutter代码布局实战
  7. Android(安卓)jni编程浅入深出之-- 与原生代码通信
  8. 开发Android网站客户端
  9. Android(安卓)的 intent (手抄)

随机推荐

  1. Android事件分发机制
  2. Android(安卓)RSA 与标准Java RSA实现区
  3. Android学好Shape不再依赖美工
  4. Android仿人人客户端
  5. Android(安卓)开源网络框架(Android-Async
  6. 通读Android文档系列 THREE
  7. Android框架揭秘读书笔记
  8. Android控件显示和隐藏
  9. 《Android底层开发技术》学习总结
  10. Xamarin Mono For Android(安卓)4.6.0700