我有许多工作的模拟类,它们代替了对Windows API的实际调用。但是,我在为使用FormatMessageW标志时利用FORMAT_MESSAGE_ALLOCATE_BUFFER的功能拼凑而成。

使用FormatMessageW函数时,我首先声明缓冲区如下:

wchar_t * buffer = nullptr;


然后,我按地址作为lpBuffer参数传递缓冲区(预期类型为LPWSTR):

reinterpret_cast<::LPWSTR>(&buffer)


Windows API函数将自动创建正确大小的缓冲区。

我通过去除换行符,从宽字符转换为多字节字符等来进一步处理缓冲区。

为了完全对输出缓冲区的清理进行单元测试,我试图通过让函数简单地返回预定义的字符串(将成为模拟对象的成员)来模拟FormatMessageW调用。

为了简化问题,以下代码尝试复制我的问题:

// represents my mock class
class mocker
{

public:
    // takes a wchar_t pointer and attempts to reassign it
    int mockFunction(wchar_t * buffer)
    {
        // assigns local copy of wchar_t pointer!
        buffer = &message[0];

        return message.length();
    }

protected:

    std::wstring message = L"test";
};

// test code
mocker mocking;
wchar_t * buffer = nullptr;
auto size = mocking.mockFunction(&buffer);

// at this point buffer is still null
// but I want the buffer to point to L"test"


有没有一种方法可以实现我将指针重定向到现有std::wstring的目标,而无需更改int mockFunction(wchar_t * buffer)的实现?

最佳答案

您所追求的可能是将此方法与FORMAT_MESSAGE_ALLOCATE_BUFFER选项一起使用。您可以在此处找到此选项的示例用法:

https://support.microsoft.com/en-us/kb/256348

它看起来如下:

HLOCAL pBuffer;   // Buffer to hold the textual error description.
// ....
ret = FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | // Function will handle memory allocation.
                FORMAT_MESSAGE_FROM_HMODULE | // Using a module's message table.
                FORMAT_MESSAGE_IGNORE_INSERTS,
                hInst, // Handle to the DLL.
                dwErrorMsgId, // Message identifier.
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language.
                (LPTSTR)&pBuffer, // Buffer that will hold the text string.
                ERRMSGBUFFERSIZE, // Allocate at least this many chars for pBuffer.
                NULL // No insert values.
                    );


HLOCAL定义为typedef HANDLE HLOCAL;HANDLEtypedef void *HANDLE;。因此,在上面的示例中,&pBuffer将指针返回指针,然后将其强制转换为也是指针的LPTSTR。在FormatMessage内部,检查是否使用了FORMAT_MESSAGE_ALLOCATE_BUFFER,如果是,则将buffer参数强制转换为(可能),HLOCAL* pToAllocBuffer = reinterpret_cast<HLOCAL*>(buffer),然后再转换为*pToAllocBuffer = LocalAlloc(.....)

因此,在您的模拟函数中,您也必须首先进行此类丑陋的转换:

wchar_t * buffer = nullptr;
auto size = mocking.mockFunction(reinterpret_cast<wchar_t * >(&buffer));


mockFunction内部:

wchar_t ** buffer = reinterpret_cast<wchar_t ** >(buffer);


现在您可以像这样将内存分配给缓冲区:

*buffer = [HERE YOUR ALLOCATION];


不要这样做:


  //分配wchar_t指针的本地副本...


如果要分配本地副本,则它将在函数返回时释放,必须使用new

10-08 12:02