私のコードは機能しますが、P/Invoke内のメモリが怖いです。
これが、ネイティブC++コードから呼び出すデリゲートです。
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public delegate string CommandCallbackDelegate([MarshalAs(UnmanagedType.LPWStr)] string command
, [MarshalAs(UnmanagedType.LPWStr)] string arg1
, [MarshalAs(UnmanagedType.LPWStr)] string arg2
);
そしてC#では、デリゲートをネイティブDLLに渡しました。
private static GCHandle _gcHandle;
public static void RegisterCommandCallback(CommandCallbackDelegate fun) { _gcHandle = GCHandle.Alloc(fun);
if (IntPtr.Size == 8)
RegisterCommandCallback_x64(fun);
else
RegisterCommandCallback_x86(fun);
}
また、ネイティブDLLでは、関数ポインターを取得した後、メソッドを正常に呼び出して、String
C#から返されたものを取得できます。
typedef LPCWSTR (WINAPI* PFN_CommandCallback)( LPCWSTR wszCommand, LPCWSTR wszArg1, LPCWSTR wszArg2);
PFN_CommandCallback g_pfnCommandCallback = ....;
LPCWSTR wszRet = g_pfnCommandCallback( L"CMD", L"ARG1", L"ARG2");
ご覧のとおり、C#メソッドはString
ネイティブDLLに戻りますが、返されたアンマネージメモリがGCによって再処理されるかどうかはわかりません。
上記のコードは機能しますが、解放されたばかりのメモリにアクセスしているのではないかと思います。