5

RPCサーバーとして機能するWindowsシステムサービスと、対応するクライアントを両方ともC++で実装しています。プレーンなWindowsRPC機能を使用しています。

RPCクライアントからサーバーへの文字列の受け渡しは簡単です。次のように、IDLファイルで関数パラメータを宣言するだけです。

[in, string] wchar_t* myString

MIDLはメモリ割り当ての魔法を処理します。御馳走のように動作します。

変更されたクライアント文字列を返すことも簡単です。

[in, out, string] wchar_t* myString

ただし、クライアント側で文字列のサイズを適切に設定する必要があります。

問題:

サーバーからクライアントに文字列を返す必要があります。クライアントでそれらがどれくらい大きくなるかわからないので、クライアントでのメモリ割り当てはオプションではありません。

非常に大量のメモリ、たとえば10Kを割り当てることができます。これは、サーバーが返す可能性のあるすべての文字列に十分な量ですしかし、それはリソース(メモリ、ネットワーク)の膨大な浪費であり、サーバーがより大きな文字列を返す必要がないことを私はまだ確信できません。

私が試したこと:

他にも、Microsoftのstroutサンプルで使用されている手法を試しました。初めてRPC関数を呼び出すと機能しましたが、2回目に呼び出すとサーバーがクラッシュしました。

4

1 に答える 1

8

MSDNページのMultipleLevelsof 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 に答える