Windows FormatMessage 的安全/灵活外观
我需要使用 FormatMessage() 来项目,但我不喜欢它可怕的界面。 有谁知道有一个外观可以整理它,同时仍然允许替换参数?
我刚刚阅读了 FastFormat 简介的第二部分,并且正在考虑编写一个FormatMessage() 的扩展名(或询问FastFormat 项目团队(如果他们正在开发中),但我我渴望尽快得到一些东西,所以如果有其他像样的东西,我可能会抓住它。
我想要的是能够编写如下代码:
HINSTANCE netevent = ::LoadLibrary("netevent.dll");
std::string msg = LookupError(netevent, EVENT_SERVICE_START_FAILED_II,
"child-svr", "parent-svr", "ship happens");
::puts(msg.c_str());
它将给出结果:
The child-svr service depends on the parent-svr service which failed to start be cause of the following error:
ship happens
我构建的当前包装器具有接口:
std::string LookupError(HINSTANCE hinst, DWORD id, ...);
这有两个问题:
- 它不是类型安全的,因为它很容易传递任何类型-
int
、std::string
、void*
- 不是const char*
- 很容易与参数数量以及表示错误的格式字符串所需的数量
考虑到 FastFormat 在类型方面的能力-安全,我想知道是否有办法遵循其机制来处理 FormatMessage()。
I need to use FormatMessage() for a project, but I don't like its scary interface. Does anyone know of a facade that tidies it up while still allowing for the replacement parameters?
I just read the second part of the FastFormat introduction, and am considering writing an extension for FormatMessage() (or asking the FastFormat project team if they've got one in the works), but I'm keen to get something asap, so if there's anything else decent out there I'd probably grab that instead.
What I want is to be able to write code such as:
HINSTANCE netevent = ::LoadLibrary("netevent.dll");
std::string msg = LookupError(netevent, EVENT_SERVICE_START_FAILED_II,
"child-svr", "parent-svr", "ship happens");
::puts(msg.c_str());
Which would give the result:
The child-svr service depends on the parent-svr service which failed to start be cause of the following error:
ship happens
The current wrapper I've built has the interface:
std::string LookupError(HINSTANCE hinst, DWORD id, ...);
There are two problems with this:
- It's not type-safe, since it's easy to pass any type -
int
,std::string
,void*
- that is notconst char*
- It's easy to mismatch the number of arguments with the number required by the format string representing the error
Given the abilities of FastFormat in terms of type-safety, I want to know if there's a way to follow its mechanisms to deal with FormatMessage().
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于编译器无法检查要插入格式字符串的参数数量,因此不可能在编译时使其真正类型安全。
您只需对不同数量的插入参数进行一些重载,然后使用诸如
boost::any
等灵活的内容指定插入的值,就可以实现大部分目标。 因此,两个参数的重载将是:当您从 arg1 检索值时,如果您尝试获取错误的类型,boost 将抛出异常,因此您只需要检查格式字符串并尝试获取每个参数所需的类型。
或者,您可以使用模板和 std::ostringstream (或 boost::lexical_cast)来获得非常灵活的版本; 再次,会有重载来允许参数数量变化,所以这里是单参数版本:
这样,只要可以流式传输传递的类型,您就可以从每个参数获取一个字符串,并且只要可以流式传输,就不需要其他任何东西因为格式字符串期望只插入字符串。
As the number of parameters to be inserted into the format string cannot be checked by the compiler, it is impossible to make this truly type-safe at compile time.
You can get most of the way there by just having a few overloads for different numbers of inserted parameters, and then specifying the inserted values with something flexible like
boost::any
. So the overload for two parameters would be:When you retrieve the value from
arg1
, boost will throw if you try to get the wrong type, so you just need to examine the format string and try to get the required type from each argument.Alternatively you could use templates and std::ostringstream (or boost::lexical_cast) for a very flexible version; again there would be overloads to allow the number of arguments to vary, so here's the single-argument version:
That way you can get a string from each argument as long as the passed type can be streamed, and nothing else should be required as long as the format strings expect only strings to insert.
C++ 格式库 允许格式化与
GetLastError()< 返回的错误代码相对应的本机 Windows 错误消息/code> 和 POSIX 错误消息对应于
errno
给出的错误。 例如:使用
FormatMessage
API函数获取Windows错误消息。 您还可以使用fmt::format_windows_error
格式化错误消息,这样不会引发异常。 有关更多详细信息,请参阅系统错误。免责声明:我是 C++ Format 的作者
The C++ Format library allows formatting native Windows error messages corresponding to error codes returned by
GetLastError()
and POSIX error messages corresponding to errors given byerrno
. For example:Windows error message is obtained using the
FormatMessage
API function. You can also format an error message withfmt::format_windows_error
which doesn't throw an exception. See System Errors for more details.Disclaimer: I'm the author of C++ Format