C#とC++間でchar*もしくはLPSZをやり取りする

C#からC++のDLLを呼び出すためにDllImportしたときにchar*が引数にある場合のやり取りの仕方です。

C++側はシグネチャを持つコードがあった場合

// C++側宣言
uint32_t __stdcall Function(char* szMessage);

// もしくは
uint32_t __stdcall Function(LPSTR szMessage);

C#側の相互運用時の呼び出し方法は以下の通りです。

// szMessage が[IN]だけの場合
[DllImport("Hoge.dll", EntryPoint="Function", /* CharSet = CharSet.Ansi */)]
public static extern int Function(string szMessage);

// szMessage が[OUT]の場合
[DllImport("Hoge.dll", EntryPoint="Function", /* CharSet = CharSet.Ansi */)]
public static extern int Function([MarshalAs(UnmanagedType.LPStr)]StringBuilder szMessage);

[IN]の場合、特に気にせずstringで渡してしまえば問題ないです。もし渡した先でszMessageが書き換えられた場合、C#側でAccessViolationExceptionが発生します。

[OUT]の場合(C++で*charが書き換わる場合)、呼び出し側で以下のように記述する必要があります。

public int MyFunction(ref string message)
{
    StringBuilder szMessage = new StringBuilder(256);

    int iRet = Function(szMessage);

    message = szMessage.ToString();
    return iRet;
}

StringBuilderは必ずキャパシティを指定します。値を指定しなかったり、C++側でバッファを超えるとAccessViolationExceptionが発生します。

参考 - MSDN

文字列に対する既定のマーシャリング