一个简单实用的log tool
-- 多线程下打印可能会乱
-- 没有分级打印
-- 没有支持debugview
应付一般的debug需求还是可以的,实际中一直在用!
逐步完善吧!
另外参考一个开源的log工具liblogger -- 架构清晰 C语言实现
http:///projects/liblogger/
|
文件: | liblogger_0.1.zip |
大小: | 158KB |
下载: | 下载 |
|
-------------------------------------------------
VC6下不支持可变参数宏__VA_ARGS__
int fprintf(FILE *stream, const char *format, ...)
fprintf转化并格式化地写入输出流。返回值是写入的字符个数;或者为负数,如果有错误发生。
int printf(const char *format, ...)
printf(...)与fprintf(stdout, ...)等价。
int sprintf(char *s, const char *format, ...)
sprintf与printf相同,只是输出被写入字符串s,并且以’\0’结束。s必须足够大以容纳结果。函数返回不包括’\0’的字符数。
int vprintf(const char *format, va_list arg)
函数vprintf与printf等价,只是用arg替换了变量参数列表,arg由va_start宏初始化,并且va_arg可能会调用它。
int vfprintf(FILE *stream,const char * format,va_list ap)
vfprintf()会根据参数format字符串来转换并格式化数据,然后将结果输出到参数stream指定的文件中,直到出现字符串结束(’\0’)为止。
int _vsnprintf(char *, size_t, const char *, va_list)
int vsprintf(char *, const char *, va_list)
DebugOutputString -- 支持debugview
功能:发送一个字串到调试器的显示。
函数原型:void WINAPI OutputDebugString( LPCTSTR lpOutputString );
一.最简单的用法
#define MAX_DBG_MSG_LEN (1024)
char[MAX_DBG_MSG_LEN];
sprintf(msgbuf, "LastError=%ld\n", GetLastError());
OutputDebugString(msgbuf);
二.扩展的用法
按照printf的风格的对OutputDebugString进行封装
#define MAX_DBG_MSG_LEN (1024)
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);va_end(ap);
OutputDebugString(buf);
}
使用:
__dbg_printf( "LastError=%ld\n", GetLastError());
三.进一步的扩展
对DEBUG和RELEASE下的区分.
ifdef _DEBUG
static void __dbg_printf (const char * format,...)
{
char buf[MAX_DBG_MSG_LEN];
va_list ap;
va_start(ap, format);
_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
OutputDebugString(buf);
}
#else
static void __dbg_printf (const char * format,...) {}
#endif
----------------------------------------------------
使用方法:
假设有class CTestApp, class CTestModule, 对应有两个.cpp文件testapp.cpp, testmodule.cpp
1)在testapp.cpp中: #include "log.h"
2)在testapp.cpp中: DefineVar();
3)在testapp.cpp类构造函数中: CTestApp::CTestApp(){TOpenFile(); ...; }
4)在testapp.cpp类析构函数中: CTestApp::~CTestApp(){...; TCloseFile();}
5)在testapp.cpp类其他函数中: CTestApp::SomeFunc(){...; LogText("Start to log data\n"); LogData("app value: %d\n", m_lValue);...;}
6)在testmodule.cpp中: #include "log.h"
7)在testmodule.cpp类其他函数中: CTestModule::SomeFunc(){...; LogData("module value: %d\n", m_lValue);...;}
8)要使得正式release版本不产生LOG,只需将log.h文件中"#define TEST" 注释掉即可,不需要删除所有LOG相关的宏定义
9)所有的LOG文件请缺省放置在C:\DebugLog\目录下,不同的模块请更改LOGFILENAME中tModule.txt的名字
一些格式要求:
1)错误情况,极少发生的事件,在LOG时加"!"前缀,如:LogText("! Parameter Error\n");
2)较少发生的事件,如用户调用,在LOG时加"#"前缀,如:LogText("# Seeking - SetPosition\n");
3)经常重复发生的事件不要加任何前缀
4)需要LOG系统时间时,调用LogSysTime()即可,如:LogSysTime(); LogData("Receive %n Bytes\n", lLength);
5)希望减少重复事件LOG的次数,可用到g_lLogCount,如:if(g_lLogCount%100==0) LogText("Sth is working\n"); g_lLogCount1++;
6)需要对齐或缩进用\t,64位整数用%I64d,如:LogData("\t frame pts: %I64d\n", tStart); LogData("\t frame size: %d\n", lLength);
#include "log.h"
DefineVar();
int main()
{
int i = 3;
TOpenFile();
LogText("--------------------\n")
LogData("i: %d, const : %d\n", i, 5);
LogSysTime();
LogData("---- i: %d\n", i);
LogData("+++++++++++++++++++\n");
TCloseFile();
return 0;
}
|
//=====================================================
//simple log tool for debug
//=====================================================
#ifndef _LOGTOOL_H_
#define _LOGTOOL_H_
#include <windows.h>
#include <stdio.h>
#define TEST
#define LOGFILENAME "C:\\DebugLog\\tModule.txt"
#ifdef TEST
/* #ifndef EnableModuleLog
#pragma message("@ log invalid: need define macro EnableModuleLog before log.h to enable log!!")
#else
#pragma message("@ enable this module log!!")
#endif
*/
#ifdef __cplusplus
extern "C" {
#endif
extern FILE* g_pLogFile;
extern char g_LogTextBuf[256];
extern LONG g_lLogCount1;
extern LONG g_lLogCount2;
#ifdef __cplusplus
}
#endif
/* #define LogData vl_printf
#ifdef EnableModuleLog
static void vl_printf(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(g_pLogFile, fmt, ap);
va_end(ap);
}
#define LogText(str) { \
sprintf(g_LogTextBuf,str); \
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
}
#define LogSysTime() { \
SYSTEMTIME st; \
GetLocalTime(&st); \
sprintf(g_LogTextBuf,"[%02u:%02u:%02u:%03u] ",st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);\
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
}
#else
static void vl_printf(const char* fmt, ...) {}
#define LogText(str)
#define LogSysTime()
#endif
*/
#define LogData vl_printf
static void vl_printf(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(g_pLogFile, fmt, ap);
va_end(ap);
}
#define LogText(str) { \
sprintf(g_LogTextBuf,str); \
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
}
#define LogSysTime() { \
SYSTEMTIME st; \
GetLocalTime(&st); \
sprintf(g_LogTextBuf,"[%02u:%02u:%02u:%03u] ",st.wHour,st.wMinute,st.wSecond,st.wMilliseconds);\
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
}
#define TOpenFile() { \
CreateDirectory("C:\\DebugLog",NULL); \
g_pLogFile=fopen(LOGFILENAME,"w"); \
SYSTEMTIME st; \
GetLocalTime(&st); \
sprintf(g_LogTextBuf,"====Open file at %02u:%02u:%02u====\n",st.wHour,st.wMinute,st.wSecond );\
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
}
#define TCloseFile() { \
SYSTEMTIME st; \
GetLocalTime(&st); \
sprintf(g_LogTextBuf,"====Close file at %02u:%02u:%02u====\n",st.wHour,st.wMinute,st.wSecond );\
fwrite(g_LogTextBuf,strlen(g_LogTextBuf),1,g_pLogFile);\
fclose(g_pLogFile); \
}
#define DefineVar() \
FILE* g_pLogFile; \
char g_LogTextBuf[256]; \
LONG g_lLogCount1=0; \
LONG g_lLogCount2=0;
#define FlushData() fflush(g_pLogFile)
#else
#pragma warning(disable: 4002 4003)
#define LogData(fmt,var)
#define LogText(str)
#define LogSysTime()
#define TOpenFile()
#define TCloseFile()
#define DefineVar()
#define FlushData()
#endif //TEST
#endif //_LOGTOOL_H_
|