5

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

将字符串从 RPC 客户端传递到服务器很容易。只需像这样在 IDL 文件中声明函数参数:

[in, string] wchar_t* myString

MIDL 将负责内存分配魔法。像一种享受一样工作。

返回修改后的客户端字符串也很容易:

[in, out, string] wchar_t* myString

不过,这需要我在客户端正确调整字符串的大小。

问题:

我需要将字符串从服务器返回到客户端。我不知道客户端会有多大,所以客户端上的内存分配不是一个选项。

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

我尝试了什么:

在许多其他事情中,我尝试了 Microsoft 的strout示例中使用的技术。第一次调用 RPC 函数时它工作正常,但第二次调用时服务器崩溃。

4

1 回答 1

8

MSDN 页面Multiple Levels of Pointers让我走上了正轨。通过那里给出的示例和解释,我设法使其工作。精华部分如下:

IDL 文件:

error_status_t ReturnsString
(
   [out]                   long*     size,
   [out, size_is(, *size)] wchar_t** outString
);

服务器功能:

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;
}

我不知道为什么需要乘以 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);
于 2012-04-22T22:31:06.027 回答