wenjiang 的个人资料morning's blog照片日志列表更多 工具 帮助

日志


6月30日

实现了VC6 的 __FUNCTION__,附上一个调试辅助类

利用 dbg api 实现了 vc6 下的 __FUNCTION__ ,意外发现 在使用 /ZI 时 VC7.1 的 __LINE__ 的实现很有意思.
 
源代码:
#ifdef __cplusplus
class clsT1
{
public:
 virtual void Test(int x=0)
 {
  DbgPrint(_T("测试\n"));
 }
};
class clsT2:public clsT1
{
public:
 void Test(int x=0)
 {
  DbgPrint(_T("测试\n"));
  clsT1::Test(x);
 }
};
#endif
int main(int argc, char* argv[])
{
 _TRACE_FUNCTION_();
 DbgPrintA("测试\n");
 DbgPrintW(L"测试\n");
#ifdef __cplusplus
 clsT2  _t2;
 _t2.Test();
#endif
//  getchar();
 return 0;
}
 
输出效果:
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(30) : <main>: ++
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(31) : <main>: 测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(32) : <main>: 测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(21) : <clsT2::Test>:测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(12) : <clsT1::Test>:测试
D:\My Documents\Visual C++ Projects\6.0\testcpp\testc.cpp(30) : <main>: --,Escaped:0
 
头文件(兼容C源代码,多线程安全的,因为内部的部分实现使用了线程存储,如果有人知道如何追踪C代码的函数过程的,请分享):
//------------------------------------------------------------------------------------------------------------------------------------------
// 参数
// _DBG_LIB_NAME ,用于控制输出的前缀
// 开关,关掉输出
#ifndef _DBG_GLOBAL_SWITCH
 #define _DBG_GLOBAL_SWITCH 1
#endif
// 开关,是否总是使用 outputdebugstring,即使是在命令行模式下
#ifndef _DBG_FORCEDBGSTR_SWITCH
 #define _DBG_FORCEDBGSTR_SWITCH 0
#endif
//  开关,是否仅显示 函数名(隐去 文件名,行号)
#ifndef _DBG_SIMPLE_SWITCH
 #define _DBG_SIMPLE_SWITCH 0
#endif
// 优化 assert 的行为
// assert 使用 MessageBox 提示,但是这会导致一些程序无法中断下来
// _ASSERT 会循环 MessageBox,不断弹出对话框
#ifndef _DBG_BREAKIN_ASSERT
#define _DBG_BREAKIN_ASSERT 1
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"{
#endif
// 取 EIP
LIBBASE_API DWORD WINAPI GetEIP();
// __FUNCIOTN__ 模拟
#ifdef __SIMU_FUNCTION__
 LIBBASE_API LPCSTR WINAPI GetFUNCTIONA(DWORD64 Address);
 LIBBASE_API LPCWSTR WINAPI GetFUNCTIONW(DWORD64 Address);
 #undef __FUNCTION__
 #undef __WFUNCTION__
 #define __FUNCTION__  GetFUNCTIONA(GetEIP())
 #define __WFUNCTION__  GetFUNCTIONW(GetEIP())
#endif
// __LINE__ 修正
#if _MSC_VER==1310
 // 在 VC7.1 中,当设为 /ZI 时,__LINE__ 是 __LINE__Var + 1,所以,下面两个宏将无法正确展开
 #define __SIMU_LINENO__
 #undef __LINENO__
 #undef __WLINENO__
 LIBBASE_API LPCSTR WINAPI GetLINENOA(DWORD dwLine);
 LIBBASE_API LPCWSTR WINAPI GetLINENOW(DWORD dwLine);
 #define __LINENO__  GetLINENOA(__LINE__)
 #define __WLINENO__  GetLINENOW(__LINE__)
#endif
// 通用字符串连接
LIBBASE_API LPCSTR WINAPI LOC_STR_LINKA(LPCSTR psz,...);
LIBBASE_API LPCWSTR WINAPI LOC_STR_LINKW(LPCWSTR psz,...);
#ifdef __cplusplus
};
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 预格式化
#if _DBG_SIMPLE_SWITCH
 #ifndef __SIMU_FUNCTION__
  #define DEF_LOC_STDOUT_A "<" __FUNCTION__ ">: "
  #define DEF_LOC_STDOUT_W L"<" __WFUNCTION__ L">: "
 #else
  #define DEF_LOC_STDOUT_A LOC_STR_LINKA("<",__FUNCTION__,">: ",NULL)
  #define DEF_LOC_STDOUT_W LOC_STR_LINKW(L"<",__WFUNCTION__,L">: ",NULL)
 #endif
#else
 #ifndef _DBG_LIB_NAME
  #define __DBG_LIB_NAMEA ""
  #define __DBG_LIB_NAMEW L""
 #else
  #define __DBG_LIB_NAMEA "(" _DBG_LIB_NAME ")"
  #define __DBG_LIB_NAMEW L"(" _L(_DBG_LIB_NAME) L")"
 #endif
 #if !defined(__SIMU_FUNCTION__) && !defined(__SIMU_LINENO__)
  #define DEF_LOC_STDOUT_A __FILE__ "("__LINENO__") : " __DBG_LIB_NAMEA "<" __FUNCTION__ ">: "
  #define DEF_LOC_STDOUT_W __WFILE__ L"(" __WLINENO__ L") : " __DBG_LIB_NAMEW L"<" __WFUNCTION__ L">: "
 #else
  #define DEF_LOC_STDOUT_A LOC_STR_LINKA(__FILE__,"(",__LINENO__,") : ",__DBG_LIB_NAMEA,"<",__FUNCTION__,">: ",NULL)
  #define DEF_LOC_STDOUT_W LOC_STR_LINKW(__WFILE__,L"(",__WLINENO__,L") : ",__DBG_LIB_NAMEW,L"<",__WFUNCTION__,L">: ",NULL)
 #endif
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 内部参数
#define MAX_BDGBUFF 4096
//------------------------------------------------------------------------------------------------------------------------------------------
// 计时
#ifdef __cplusplus
extern "C"{
#endif
LIBBASE_API ULONGLONG WINAPI GetPerformaceCount();
#ifdef __cplusplus
};
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 输出工具
#ifdef __cplusplus // 对 C 代码不可见
template<class _Ty>
class dbgwriter_dbg
{
public:
 void put(const _Ty* str){}
};
template<class _Ty>
class dbgwriter_con
{
public:
 void put(const _Ty* str){}
};
template<>
void dbgwriter_dbg<CHAR>::put(const CHAR* str)
{
 OutputDebugStringA(str);
}
template<>
void dbgwriter_dbg<WCHAR>::put(const WCHAR* str)
{
 OutputDebugStringW(str);
}
template<>
void dbgwriter_con<CHAR>::put(const CHAR* str)
{
 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdOut != INVALID_HANDLE_VALUE)
 {
  DWORD dwRet;
  WriteConsoleA(hStdOut,str,strlen(str),&dwRet,NULL);
 }
}
template<>
void dbgwriter_con<WCHAR>::put(const WCHAR* str)
{
 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdOut != INVALID_HANDLE_VALUE)
 {
  DWORD dwRet;
  WriteConsoleW(hStdOut,str,wcslen(str),&dwRet,NULL);
 }
}
typedef dbgwriter_con<CHAR>  dbgwriter_conA;
typedef dbgwriter_con<WCHAR> dbgwriter_conW;
typedef dbgwriter_dbg<CHAR>  dbgwriter_dbgA;
typedef dbgwriter_dbg<WCHAR> dbgwriter_dbgW;
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
// 行调试
#ifdef __cplusplus
extern "C"{
#endif
typedef void (WINAPI* PFNDBGPRINT_DBGA)(LPCSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_DBGW)(LPCWSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_CONA)(LPCSTR str, ...);
typedef void (WINAPI* PFNDBGPRINT_CONW)(LPCWSTR str, ...);
typedef void (WINAPI* PFNDBGPRINTV_DBGA)(LPCSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_DBGW)(LPCWSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_CONA)(LPCSTR ptzFormat, va_list vlArgs);
typedef void (WINAPI* PFNDBGPRINTV_CONW)(LPCWSTR ptzFormat, va_list vlArgs);
LIBBASE_API PFNDBGPRINT_DBGA WINAPI _DbgPrint_DBGA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINT_DBGW WINAPI _DbgPrint_DBGW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINT_CONA WINAPI _DbgPrint_CONA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINT_CONW WINAPI _DbgPrint_CONW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINTV_DBGA WINAPI _DbgPrintV_DBGA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINTV_DBGW WINAPI _DbgPrintV_DBGW(LPCWSTR pszTag);
LIBBASE_API PFNDBGPRINTV_CONA WINAPI _DbgPrintV_CONA(LPCSTR pszTag);
LIBBASE_API PFNDBGPRINTV_CONW WINAPI _DbgPrintV_CONW(LPCWSTR pszTag);
#ifdef __cplusplus
};
#endif
#define DbgPrint_CONA _DbgPrint_CONA(DEF_LOC_STDOUT_A)
#define DbgPrint_CONW _DbgPrint_CONW(DEF_LOC_STDOUT_W)
#define DbgPrint_DBGA _DbgPrint_DBGA(DEF_LOC_STDOUT_A)
#define DbgPrint_DBGW _DbgPrint_DBGW(DEF_LOC_STDOUT_W)
#define DbgPrintV_CONA _DbgPrintV_CONA(DEF_LOC_STDOUT_A)
#define DbgPrintV_CONW _DbgPrintV_CONW(DEF_LOC_STDOUT_W)
#define DbgPrintV_DBGA _DbgPrintV_DBGA(DEF_LOC_STDOUT_A)
#define DbgPrintV_DBGW _DbgPrintV_DBGW(DEF_LOC_STDOUT_W)
#ifdef _UNICODE
 #define DbgPrint_CON DbgPrint_CONW
 #define DbgPrint_DBG DbgPrint_DBGW
 #define DbgPrintV_CON DbgPrintV_CONW
 #define DbgPrintV_DBG DbgPrintV_DBGW
#else
 #define DbgPrint_CON DbgPrint_CONA
 #define DbgPrint_DBG DbgPrint_DBGA
 #define DbgPrintV_CON DbgPrintV_CONA
 #define DbgPrintV_DBG DbgPrintV_DBGA
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
//函数过程追踪
#ifdef __cplusplus // 对 C 代码不可见
template <class _Wy>
class DBGFUNCTRACE
{
protected:
 CStdString m_strTag;//必须保存原始字符串,而不是指针,因为可能对方是临时内存块
 ULONGLONG dwEnter;
public:
 DBGFUNCTRACE(LPCTSTR pszTag)
 {
  m_strTag=pszTag?pszTag:_T("");
  
  CStdString _str;
  _str.Format(_T("%s++\n"),m_strTag.c_str());
  _Wy().put(_str.c_str());
  dwEnter = GetPerformaceCount();
 }
 ~DBGFUNCTRACE()
 {
  CStdString _str;
  _str.Format(_T("%s--,Escaped:%lu\n"),m_strTag.c_str(),GetPerformaceCount() - dwEnter);
  _Wy().put(_str.c_str());
 }
};
#ifdef _UNICODE
 #define _TRACE_FUNCTION_CON() DBGFUNCTRACE<dbgwriter_conW> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_W);
 #define _TRACE_FUNCTION_DBG() DBGFUNCTRACE<dbgwriter_dbgW> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_W);
#else
 #define _TRACE_FUNCTION_CON() DBGFUNCTRACE<dbgwriter_conA> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_A);
 #define _TRACE_FUNCTION_DBG() DBGFUNCTRACE<dbgwriter_dbgA> _FuncTrace ## __LINE__(DEF_LOC_STDOUT_A);
#endif
#else // !__cplusplus
#define _TRACE_FUNCTION_CON() // C 编译方式下不支持
#define _TRACE_FUNCTION_DBG() // C 编译方式下不支持
#endif

//------------------------------------------------------------------------------------------------------------------------------------------
//这是最终的映射
#if (_DBG_GLOBAL_SWITCH && ((defined(_DBG) && _DBG) || defined(_DEBUG)))
 #if  defined(_CONSOLE) && (_DBG_FORCEDBGSTR_SWITCH==0)
  #define DbgPrintA      DbgPrint_CONA
  #define DbgPrintW      DbgPrint_CONW
  #define DbgPrintVA      DbgPrintV_CONA
  #define DbgPrintVW      DbgPrintV_CONW
  #define _TRACE_FUNCTION_()    _TRACE_FUNCTION_CON()
 #else
  #define DbgPrintA      DbgPrint_DBGA
  #define DbgPrintW      DbgPrint_DBGW
  #define DbgPrintVA      DbgPrintV_DBGA
  #define DbgPrintVW      DbgPrintV_DBGW
  #define _TRACE_FUNCTION_()    _TRACE_FUNCTION_DBG()
 #endif
#else // DbgPrint
 #define DbgPrintA __noop
 #define DbgPrintW __noop
 #define DbgPrintVA __noop
 #define DbgPrintVW __noop
 #define _TRACE_FUNCTION_()
#endif // DbgPrint
#ifdef _UNICODE
 #define DbgPrint DbgPrintW
#else
 #define DbgPrint DbgPrintA
#endif
//------------------------------------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"{
#endif
LIBBASE_API void WINAPI assert_breakin(const char * exp, void * file, unsigned fileno);
#ifdef __cplusplus
};
#endif
#include <assert.h>
#include <crtdbg.h>
#if _DBG_BREAKIN_ASSERT
 #ifdef assert
  #undef assert
 #endif
 #ifdef _DEBUG
 #define assert(exp) (void)( (exp) || (assert_breakin(#exp, __FILE__, __LINE__), 0) )
 #else
  #define assert(exp)     ((void)0)
 #endif
#endif
#ifdef _ASSERT
 #undef _ASSERT
#endif
#ifdef ASSERT
 #undef ASSERT
#endif
#ifdef VERIFY
 #undef VERIFY
#endif
#define ASSERT(f)          assert(f)
#define _ASSERT(f)          assert(f)
#ifdef _DEBUG
 #define VERIFY(f)          ASSERT(f)
#else
 #define VERIFY(f)          ((void)(f))
#endif
6月28日

I did not speak out

First they came for the socialists, and I did not speak out
because I was not socialist.
Then they came for the trade unionists, and I did not speak out
because I was not trade unionists.
Then  they came for the Jews, and I did not speak out
because I was not Jew.
Then they came for me, and there was no one left to speak for me.
  
  -- Pastor Martin Niemöller

6月25日

email 有益工作效率

最近一段时间,除了偶尔看一下留言外,基本上没有用msn/qq,减少了中途被打岔的可能.
当然,也节省了近100M的内存.

几分钟收一次信,可以保证重要的信息不被错过.
6月24日

完成一个轻量级的高速UI库

一直打算做的一件事,终于下决心行动起来并把它完成了.支持常见的格式,也支持不常见的各种bmp变形格式,支持多种加载/绘图方式,在非常追求性能的情况下,可以使用32位缓存绘图方式,速度极快.