经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
DirectX11--HR宏关于dxerr库的替代方案
来源:cnblogs  作者:X_Jun  时间:2018/12/25 9:13:21  对本文有异议

DirectX11 With Windows SDK完整目录

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

综述

参考文章:https://blogs.msdn.microsoft.com/chuckw/2012/04/24/wheres-dxerr-lib/

在龙书11中所使用的HR宏和dxerr库是一个比较实用的错误原因追踪工具。D3D中的某些函数拥有返回值HRESULT,通过dxerr库,可以将错误码转换成错误详细信息的字符串。

在DirectX SDK中,包含了头文件dxerr.h和库文件dxerr.lib,在以往的做法包含了DX SDK后,就可以直接使用dxerr了。但如果是要编写基于Windows SDK的Direct3D程序,在Windows SDK 8.0以上已经没有了dxerr库。

此时此刻,你仍然有两种选择来脱离对DirectX SDK的依赖:

  1. 寻找较新的dxerr.hdxerr.cpp源码来编译出dxerr.lib,或者直接加入你的项目当中;
  2. 直接抛弃dxerr

新的dxerr源码

微软已经将dxerr库开源了,下面的链接可以下载,如果不放心的话,你也可以到上面的参考文章去下载。

dxerr_nov2015.zip下载地址

在我以往的DirectX11项目中,则是从DXUT中拉过来的dxerr

DXUT Github/Core

但要注意的是,由于新的dxerr.h仅提供了DXTrace的Unicode字符集版本,需要将原来的__FILE__替换为__FILEW__,并在项目属性页中将字符集设置为Unicode

抛弃dxerr库

自Windows SDK 8.0起,HRESULT值关于DirectX图形API的错误消息字符串映射已经加入到FormatMessage函数中。我们可以直接脱离对dxerr的依赖,并使用该函数来直接获取错误消息字符串。因此,dxerr库也就没有必要在Windows SDK 8.0以上版本保留了。

FormatMessageW函数--获取格式化消息字符串

鉴于我们只是要获取错误码对应的字符串信息,这里就简单提及一下该函数的部分用法:

  1. DWORD FormatMessageW(
  2. DWORD dwFlags, // [In]FORMAT_MESSAGE系列宏
  3. LPCVOID lpSource, // [In]直接填NULL
  4. DWORD dwMessageId, // [In]传入函数异常时返回的HRESULT
  5. DWORD dwLanguageId, // [In]语言ID
  6. LPTSTR lpBuffer, // [In]用于输出消息字符串的缓冲区
  7. DWORD nSize, // [In]WCHAR缓冲区可容纳元素个数
  8. va_list *Arguments // [In]直接填NULL
  9. );

DXTraceW函数

这里我将dxerrDXTraceW函数的实现进行了修改,由于现在错误码信息为中文,为此也顺便把错误窗口和输出也汉化了。只需要包含Windows.hsal.h就可以使用。
函数原型:

  1. // ------------------------------
  2. // DXTraceW函数
  3. // ------------------------------
  4. // 在调试输出窗口中输出格式化错误信息,可选的错误窗口弹出(已汉化)
  5. // [In]strFile 当前文件名,通常传递宏__FILEW__
  6. // [In]hlslFileName 当前行号,通常传递宏__LINE__
  7. // [In]hr 函数执行出现问题时返回的HRESULT值
  8. // [In]strMsg 用于帮助调试定位的字符串,通常传递L#x(可能为NULL)
  9. // [In]bPopMsgBox 如果为TRUE,则弹出一个消息弹窗告知错误信息
  10. // 返回值: 形参hr
  11. HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox);

函数实现:

  1. HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr,
  2. _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox)
  3. {
  4. WCHAR strBufferFile[MAX_PATH];
  5. WCHAR strBufferLine[128];
  6. WCHAR strBufferError[300];
  7. WCHAR strBufferMsg[1024];
  8. WCHAR strBufferHR[40];
  9. WCHAR strBuffer[3000];
  10. swprintf_s(strBufferLine, 128, L"%lu", dwLine);
  11. if (strFile)
  12. {
  13. swprintf_s(strBuffer, 3000, L"%ls(%ls): ", strFile, strBufferLine);
  14. OutputDebugStringW(strBuffer);
  15. }
  16. size_t nMsgLen = (strMsg) ? wcsnlen_s(strMsg, 1024) : 0;
  17. if (nMsgLen > 0)
  18. {
  19. OutputDebugStringW(strMsg);
  20. OutputDebugStringW(L" ");
  21. }
  22. // Windows SDK 8.0起DirectX的错误信息已经集成进错误码中,可以通过FormatMessageW获取错误信息字符串
  23. // 不需要分配字符串内存
  24. FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  25. nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  26. strBufferError, 256, nullptr);
  27. WCHAR* errorStr = wcsrchr(strBufferError, L'\r');
  28. if (errorStr)
  29. {
  30. errorStr[0] = L'\0'; // 擦除FormatMessageW带来的换行符(把\r\n的\r置换为\0即可)
  31. }
  32. swprintf_s(strBufferHR, 40, L" (0x%0.8x)", hr);
  33. wcscat_s(strBufferError, strBufferHR);
  34. swprintf_s(strBuffer, 3000, L"错误码含义:%ls", strBufferError);
  35. OutputDebugStringW(strBuffer);
  36. OutputDebugStringW(L"\n");
  37. if (bPopMsgBox)
  38. {
  39. wcscpy_s(strBufferFile, MAX_PATH, L"");
  40. if (strFile)
  41. wcscpy_s(strBufferFile, MAX_PATH, strFile);
  42. wcscpy_s(strBufferMsg, 1024, L"");
  43. if (nMsgLen > 0)
  44. swprintf_s(strBufferMsg, 1024, L"当前调用:%ls\n", strMsg);
  45. swprintf_s(strBuffer, 3000, L"文件名:%ls\n行号:%ls\n错误码含义:%ls\n%ls您需要调试当前应用程序吗?",
  46. strBufferFile, strBufferLine, strBufferError, strBufferMsg);
  47. int nResult = MessageBoxW(GetForegroundWindow(), strBuffer, L"错误", MB_YESNO | MB_ICONERROR);
  48. if (nResult == IDYES)
  49. DebugBreak();
  50. }
  51. return hr;
  52. }

注意:上面的函数是初版修改,仍需要大量的实践以验证可替代性和稳定性!

HR宏

现在的HR宏变成了这样:

  1. // ------------------------------
  2. // HR宏
  3. // ------------------------------
  4. // Debug模式下的错误提醒与追踪
  5. #if defined(DEBUG) | defined(_DEBUG)
  6. #ifndef HR
  7. #define HR(x) { HRESULT hr = (x); if(FAILED(hr)) { DXTraceW(__FILEW__, (DWORD)__LINE__, hr, L#x, true); } }
  8. #endif
  9. #else
  10. #ifndef HR
  11. #define HR(x) (x)
  12. #endif
  13. #endif

测试效果如下:

在调试输出窗口也可以看到:

DirectX11 With Windows SDK完整目录

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号