在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缓冲区。
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
这个函数指针。
要在
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
等来输出日志就可以。