C++ Windows FormatMessage的安全/灵活外观

C++ Windows FormatMessage的安全/灵活外观,c++,formatmessage,fastformat,C++,Formatmessage,Fastformat,我需要用于一个项目,但我不喜欢它可怕的界面。有人知道有一个门面可以在允许替换参数的情况下对其进行整理吗 我刚刚读了这篇文章,正在考虑为它写一篇扩展文章(或者询问项目团队是否有一篇正在进行的文章),但我很想尽快得到一些东西,所以如果有其他合适的东西,我可能会抓住它 我想要的是能够编写如下代码: HINSTANCE netevent = ::LoadLibrary("netevent.dll"); std::string msg = LookupError(netevent, EVENT_SERVI

我需要用于一个项目,但我不喜欢它可怕的界面。有人知道有一个门面可以在允许替换参数的情况下对其进行整理吗

我刚刚读了这篇文章,正在考虑为它写一篇扩展文章(或者询问项目团队是否有一篇正在进行的文章),但我很想尽快得到一些东西,所以如果有其他合适的东西,我可能会抓住它

我想要的是能够编写如下代码:

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*
  • 参数的数量很容易与表示错误的格式字符串所需的数量不匹配

鉴于在类型安全方面的能力,我想知道是否有一种方法可以遵循其机制来处理。

由于编译器无法检查插入格式字符串的参数数量,因此不可能在编译时使此类型真正安全

通过对不同数量的插入参数进行一些重载,然后使用类似于
boost::any
的灵活方法指定插入的值,您就可以实现大部分功能。因此,两个参数的过载为:

std::string FormatMessage(HINSTANCE hinst, DWORD id, const boost::any &arg1, const boost::any &arg2);
arg1
检索值时,如果尝试获取错误的类型,boost将抛出,因此只需检查格式字符串并尝试从每个参数获取所需的类型

或者,您可以使用模板和std::ostringstream(或boost::lexical_cast)来实现非常灵活的版本;同样,会有重载来允许参数的数量变化,因此这里是单参数版本:

template <class TArg1>
std::string FormatMessage(HINSTANCE hinst, DWORD id, const TArg1 &arg1)
{
    std::ostringstream arg1Stream;
    arg1Stream << arg1;
    std::string arg1String = arg1Stream.str();

    DWORD_PTR argArray = reinterpret_cast<DWORD_PTR>(arg1String.c_str());

    // ... etc
}
模板
std::字符串格式消息(HINSTANCE hinst、DWORD id、常量arg1和arg1)
{
std::ostringstream arg1Stream;
arg1Stream允许格式化与
GetLastError()
返回的错误代码对应的本机Windows错误消息,以及与
errno
给出的错误对应的POSIX错误消息。例如:

// This throws a WindowsError with the description
//   cannot open file 'madeup': The system cannot find the file specified.
// or similar (system message may vary).
const char *filename = "madeup";
LPOFSTRUCT of = LPOFSTRUCT();
HFILE file = OpenFile(filename, &of, OF_READ);
if (file == HFILE_ERROR)
  throw fmt::WindowsError(GetLastError(), "cannot open file '{}'", filename);
Windows错误消息是使用
FormatMessage
API函数获取的。您还可以使用
fmt::format\u Windows\u error
格式化错误消息,该错误消息不会引发异常。有关详细信息,请参阅


<我的作者是C++格式< /p>你想写点什么……什么?doh!抱歉。暂时修复它…有趣的想法。需要一个va_参数列表或一个32位参数数组。因此,在第一种情况下,我们需要一个可变函数,尽管它可以在您描述的函数中调用,boost::any将处理类型安全性。或者,我们可以直接构建参数数组。但我感兴趣的原因之一是FastFormat能够处理任意类型的参数,这意味着可以传递任何类型的参数,然后在调用FormatMessage()之前将其转换为char*。我认为boost::any不允许这样做