在非NDK編譯條件下使用Android Log函數

解決的需求

有些時候不能在NDK環境編譯,或者使用NDK編譯會頗費周折,而後又想使用Android系統自帶的Log類方法,那麼咱們就可使用dlopen來實現咱們的目的。好比在OpenCV中添加Android的Log打印。android

關於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方法調用app

#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);
    }
}
相關文章
相關標籤/搜索