解決的需求
有些時候不能在NDK環境編譯,或者使用NDK編譯會頗費周折,然后又想使用Android系統自帶的Log類方法,那么我們就可以使用dlopen來實作我們的目的,比如在OpenCV中添加Android的Log列印,
關于dlopen
- dlopen和dlclose對處理的lib進行參考計數,dlopen使參考計數加1,dlclose讓參考計數減1,當對庫的參考計數達到0的時候,才會把庫unmap掉,
- dlsym回傳查找到的第一個符合要求的函式地址,該地址指的是庫加載進行程虛擬地址,
- 可以使用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.
- 在呼叫了dlclose之后,再使用dlsym得到的函式是不行的,雖然當使用dlclose使得參考計數為0之后,系統并不會立馬把加載的庫給unmap掉,但是這個時間是不確定的,也許在你呼叫dlclose之后,在系統unmap之前呼叫dlsym的函式,或者本次dlclose并沒有讓參考計數為0,比如行程中還有其他地方也dlopen同一個庫,那么系統也不會unmap,這樣呼叫dlsym的函式并不會出錯,
- 如果你想dlopen一個庫之后,需要在程式中一直使用這個庫的函式,那么沒有必要呼叫dlclose,包括在程式退出之前呼叫dlclose,因為程式退出會自動unmap這些庫,但是如果你要dlopen很多庫,可能會導致虛擬地址不足的情況,那么就需要呼叫dlclose以保證不會出錯,https://stackoverflow.com/questions/26131102/is-it-safe-to-call-dlclose-after-dlsym
代碼
使用如下代碼,實作基于dlopen的Android Log方法呼叫
#include <dlfcn.h>
#include <stdarg.h>
#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);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/34306.html
標籤:Android
