0

サイズ 30 の空の文字列配列を C++ DLL に渡す C# アプリケーションを作成しています。この文字列配列を DLL に入力し、C# アプリケーションに返す必要があります。

私のコードでは、DLL からの関数呼び出しの最後にメモリの破損が見られます。

私のC++ DLLコードは次のとおりです。

SAMPLEDLL_API BOOL InitExecution (wchar_t **paszStrings, int count)
{
    for (int i = 0 ; i < count; i++)
    {
        mbstowcs(*(paszStrings + i), "Good",4);
        //*(paszStrings + i) = "Good";
    }
return TRUE;
}

私のC#コードは

string[] names = new[] { "Britto", "Regis" };
if (Wrapper1.InitExecution(ref names, names.Length) == 1)
    MessageBox.Show("Passed");

[DllImport("MFCLibrary1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 InitExecution(ref string[] Names, int count);
4

1 に答える 1

2

この現在のアプローチを機能させるにStringBuilderは、 ではなくインスタンスを渡す必要がありますstring。これは、データが呼び出し元から呼び出し先に流れているためです。文字列は出力パラメーターです。つまり、呼び出し元は文字列ごとにバッファーを割り当て、必要なバッファーの大きさを把握する必要があります。

こちらの方がずっと使いやすいBSTRです。これにより、ネイティブ コードで文字列を割り当て、マネージ コードでそれらの割り当てを解除することができます。これBSTRは、 が共有 COM ヒープに割り当てられており、p/invoke マーシャラーがそれらを理解しているためです。このわずかな変更を行うことは、呼び出し元が文字列の大きさを事前に知る必要がないことを意味します。

コードは次のようになります。

SAMPLEDLL_API BOOL InitExecution(BSTR* names, int count)
{
    for (int i = 0 ; i < count; i++)
        names[i] = SysAllocStr(...);
    return TRUE;
}

C# 側では、次のように記述します。

[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitExecution(
    [Out] IntPtr[] names, 
    int count
);

BSTR次に、から C#にマーシャリングする作業が少しありますstring

IntPtr[] namePtrs = new IntPtr[count];
InitExecution(namePtrs, namePtrs.Length);
string[] names = new string[namePtrs.Length];
for (int i = 0; i < namePtrs.Length; i++)
{
    names[i] = Marshal.PtrToStringBSTR(namePtrs[i]);
    Marshal.FreeBSTR(namePtrs[i]);
}
于 2013-10-19T10:55:40.747 に答える