10

C++ DLL の関数で、std::string を C# アプリケーションに返しています。次のようになります。

std::string g_DllName = "MyDLL";

extern "C" THUNDER_API const char* __stdcall GetDLLName()
{
    return g_DllName.c_str();
}

しかし、私の C# コードがこの関数を呼び出すと、出力ウィンドウに次のメッセージが表示されます。

Invalid Address specified to RtlFreeHeap( 00150000, 0012D8D8 )

C# での関数宣言は次のようになります。

[DllImport("MyDll", EntryPoint = "GetDLLName")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string GetDLLName();

私がオンラインで見つけたものから、削除で使用されている新しいバージョン (デバッグまたはリリースなど) の間に矛盾がある場合に、このメッセージが表示されることがあります。しかし、それが私の場合に起こっていることであるかどうかはわかりません。そのため、何が原因なのか正確にはわかりません。たぶん、MashallAs はそれと何か関係があるのでしょうか?

何か案は?

ありがとう!

4

1 に答える 1

13

問題を見つけることができました。これは、C# の定義が行われた方法でした。私が理解できることから、MarshallAs(UnmanagedType.LPStr) を文字列の戻り値の型と組み合わせて使用​​すると、完了時に文字列を解放しようとするようになります。しかし、文字列は C++ DLL から取得され、おそらくまったく異なるメモリ マネージャーから取得されるため、失敗します。たとえ失敗しなかったとしても、とにかく解放されたくありません。

私が見つけた解決策は、C# 宣言を次のように変更することでした (C++ コードは変更されていません)。

[DllImport("MyDll", EntryPoint = "GetDLLName")]
public static extern IntPtr GetDLLName();

したがって、これにより、文字列データへのポインターが返されるだけになります。そして、それを文字列に変更するには、それを Marshal.PtrToStringAnsi() に渡します

return Marshal.PtrToStringAnsi(GetDLLName());

そして、それはきれいにするために別の関数にラップされます。

このページから解決策を見つけました: http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1108

于 2009-04-28T18:16:33.607 に答える