2

DLLにコンパイルしたCコードが渡されました。次に、このコードの関数を呼び出すラッパーをVC++で作成しました。この時点まではすべて正常に機能します。このラッパーを使用するC#コードからC ++コードにC#stringbuilder(char *)を渡すのに問題があります。

これまでのところ、次の関数呼び出しを持つVC++で記述されたラッパークラスがあります。

void Wrapper::ReadStream(char* buffer, int* size)
{
    int req_sz;
    read_stream(opts, req_sz, req, buffer); //This calls the C DLL, this part works.
} 

C ++ラッパー関数ReadStreamを呼び出そうとしているときに、C#コードに問題が発生しました。同様の問題を探し回った後、C#からC ++(char *を検索する)に文字列を渡すには、文字列ビルダーを渡す必要があることがわかったので、次のことを試しました。

C#コード:

...
Wrapper wrap = new Wrapper()
...

int bufferSize = 48;
StringBuilder buffer = new StringBuilder(bufferSize);
wrap.ReadStream(buffer, ref bufferSize);

ただし、C#は関数定義をsbyte *が必要であると見なしているため、コードはコンパイルされません。これは、C#文字がユニコード(2バイト)であるのに対し、C ++文字は1バイト文字であるためですが、推奨される解決策はStringBuilderを渡すことです。

C#コードがstringbuilderをDLLに直接渡すソリューションをたくさん見てきましたが、stringbuilderをC++ラッパークラスに渡すソリューションを見つけることができません。

4

2 に答える 2

1

StringBuilderをC++側に確実に渡すことができ、Wrapper::ReadStream署名を次のように変更するだけです。

void Wrapper::ReadStream(LPWSTR buffer, int* size)

ところで、あなたはCコードを持っていると言っているので、C#から直接呼び出すことができるように変更することをお勧めします(CはC ++のサブセットであるため、CコードもC ++コードであることが多く、C++機能を追加できますクラスのようにそれに)。そうすれば、常に苦痛であるラッパーを避けることができます。

その間、ANSI文字列の代わりにUnicode文字列を使用するように変更することもお勧めします(ANSI文字列を必要とするものがない限り)。

そして最後に、COMを使用してC#側とC++側が相互に通信することをお勧めします。その場合、ReadStreamメソッドは次のようなIDLインターフェイスになります。

[object, uuid(2C5B0D36-0B34-4FEE-A0B8-B10F7A019A6D)]
interface ISomeObject : IUnknown
{
    HRESULT ReadStream([out, retval] BSTR* pbstrBuffer);
}

BSTRはCOMの文字列型です(Unicodeです)。C#側には、次のインターフェイスが表示されます。

interface ISomeObject
{
    string ReadStream();
}

渡されたバッファを入力せずに新しい文字列を返すため、「サイズ」パラメータは必要ありません(バッファが小さすぎて結果を保持できないという問題があります)。

これまでCOMを使用したことがない場合は、学習曲線が急になる可能性がありますが、このような多くの相互運用を計画している場合は、それだけの価値があります。

于 2012-10-24T14:30:47.567 に答える
1

C# Unicode 文字列をstd::wstringに渡すことができ、次に C++ コードでstd::wstring を std::string に変換して C-API に渡すことができます。

または、 Encoding ASCII GetBytesを使用して C# コードで Byte[] を取得し、配列を C++ に渡し、それをヌル終了文字列に変換して C-API に渡すことができます。私はおそらく2番目のオプションに行きます。

于 2012-10-24T13:57:51.437 に答える