在Android的c/c++代碼中使用LOG

在Android中,Java代碼通過android.util.Log輸出Log信息,同樣的本地c/c++代碼也提供了相對應而且是更多的接口。Android直接在頭文件(system/core/include/cutils/log.h)裏定義了一些日誌輸出的宏,這些宏比android.util.Log提供了更多的日誌輸出接口。因此,使用這些宏,就可以進行和java代碼中一樣的日誌輸出。宏LOGD(),LOGE(),LOGI(),LOGV(),LOGW(),LOGD()分別對應android.util.Log中的Log.d(),Log.e(),Log.i(),Log.v(),Log.w()
注意:這裏的都是把日誌輸出到Main緩衝區。
另外,關於此文最好對照着《Android LOG機制流程圖》一起來看。
log.h中對日誌輸出還提供一些更細的宏,比如對於LOGD(),還提供了LOGD_IF(),IF_LOGD(),SLOGD(),SLOGD_IF()。其中LOGD_IF()表示條件輸出,IF_LOGD()用於測試是否需要輸出,SLOGD()表示把日誌輸出到System日誌緩衝,SLOGD_IF()表示條件成立的情況下,把日誌輸出到System日誌緩衝。
注意:IF_LOGD()現在總是返回1.
因爲,LOG分了VERBOSE/DEBUG/INFO/WARN/ERROR/ASSERT等類別,簡單起見,以DEBUG爲例的實現來說明。
#ifndef LOGD
#define LOGD(...) LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#endif

#ifndef LOGD_IF
#define LOGD_IF(cond, ...) \
    ( (CONDITION(cond)) \
    ? LOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__) \
    : (void)0 )
#endif

#ifndef IF_LOGD
 #define IF_LOGD() IF_LOG(LOG_DEBUG, LOG_TAG)
#endif

#ifndef SLOGD
 #define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#endif
#ifndef SLOGD_IF
 #define SLOGD_IF(cond, ...) \
     ( (CONDITION(cond)) \
     ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \
     : (void)0 )
 #endif
 LOGD(),LOGE(),LOGI(),LOGV(),LOGW(),LOGD()其實最好後會使用以下的宏。
#ifndef LOG
#define LOG(priority, tag, ...) \
    LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
#endif
#ifndef LOG_PRI
#define LOG_PRI(priority, tag, ...)                                     \
    ({                                                                  \
       if (((priority == ANDROID_LOG_VERBOSE) && (LOG_NDEBUG == 0)) ||  \
           ((priority == ANDROID_LOG_DEBUG) && (LOG_NDDEBUG == 0))  ||  \
           ((priority == ANDROID_LOG_INFO) && (LOG_NIDEBUG == 0))   ||  \
            (priority == ANDROID_LOG_WARN)                          ||  \
            (priority == ANDROID_LOG_ERROR)                         ||  \
            (priority == ANDROID_LOG_FATAL))                            \
                (void)android_printLog(priority, tag, __VA_ARGS__);     \
    })
#endif
 
#define android_printLog(prio, tag, fmt...) \
__android_log_print(prio, tag, fmt)
而這一系列宏,最後還是調用了system/core/liblog/logd_write.c中的__android_log_print()
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
{
    va_list ap;
    char buf[LOG_BUF_SIZE];
 
    va_start(ap, fmt);
    vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
    va_end(ap);
 
    return __android_log_write(prio, tag, buf);
}
這裏還是調到了函數__android_log_write()__android_log_write()組織了參數,又調用了write_to_log這個函數指針。
關於write_to_log這個函數指針的調用詳情請參考《Android中LOG機制詳解

要在c/c++中使用Log,很簡單。通常的做法是:
定義自己的TAG_LOG宏;包含頭文件log.h;然後在需要記錄Log的地方直接用LOGV/LOGD/LOGI/LOGW/LOGE等即可。
比如,文件lights.c中就在開頭這樣寫,
#define LOG_TAG "lights"
#include <cutils/log.h> 
然後在該文件的後續部分,直接用LOGV/LOGE等來輸出日誌就可以。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章