如何将可变长度字符串从RPC服务器传递到客户端?

Hel*_*ein 4 c++ winapi rpc idl

我正在用C++实现一个Windows系统服务,它充当RPC服务器和相应的客户端.我使用普通的Windows RPC功能.

将字符串从RPC客户端传递到服务器很容易.只需在IDL文件中声明函数参数,如下所示:

[in, string] wchar_t* myString
Run Code Online (Sandbox Code Playgroud)

MIDL将负责内存分配魔术.就像一种享受.

返回修改后的客户端字符串也很简单:

[in, out, string] wchar_t* myString
Run Code Online (Sandbox Code Playgroud)

但是,这要求我在客户端正确调整字符串的大小.

问题:

我需要将字符串从服务器返回给客户端.我不知道客户端会有多大,所以客户端的内存分配不是一种选择.

可以分配一个非常大的内存,比如10K,这个数量足够大,可以用于服务器可能返回的每个字符串.但这是对资源(内存,网络)的巨大浪费,我仍然无法确定服务器永远不需要返回更大的字符串.

我尝试了什么:

Amonst许多其他的东西我尝试了微软的strout示例中使用的技术.它在第一次调用RPC函数时起作用,但在第二次调用时崩溃了服务器.

Hel*_*ein 7

MSDN页面多个指针级别让我走上正轨.通过给出的示例和解释,我设法使其工作.essentail部分如下:

IDL文件:

error_status_t ReturnsString
(
   [out]                   long*     size,
   [out, size_is(, *size)] wchar_t** outString
);
Run Code Online (Sandbox Code Playgroud)

服务器功能:

error_status_t ReturnsString (long* size, wchar_t** outString)
{
   wstring outStringWString = L"Return this to caller";

   int stringSize = sizeof(wchar_t) * (outStringWString.size() + 1);
   *outString = (wchar_t*) midl_user_allocate (stringSize * 2);
   wcscpy_s (*outString, stringSize, outStringWString.c_str());

   *size = outStringWString.size() + 1;

   return ERROR_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么乘以2(stringSize*2)是必要的,但确实如此.如果省略,则会立即发生堆损坏.

客户代码:

wchar_t** versionRPC = (wchar_t**) midl_user_allocate (sizeof(wchar_t*));
*versionRPC = NULL;     // Required to create a unique pointer
long stringSize = 0;
DWORD retVal = ReturnsString (&stringSize, versionRPC);

// Copy the returned string
wstring stringFromServer (*rpcString);

MIDL_user_free (*rpcString);
MIDL_user_free (rpcString);
Run Code Online (Sandbox Code Playgroud)

  • 您正在使用每个字符为2个字节的Unicode字符串,因此您需要多个字符串长度*sizeof(wchar)... (2认同)