2013年1月4日金曜日

P/Invokeの規定の呼び出し規約

自前のunmanagedなdllを、.NETなアプリケーションからP/Invokeで使おうとした際に  pInvokeStackImbalance で躓いたメモです。
環境は Visual Studio 2010 / .NET Framework 4.0

unmanaged DLL 側はC++でこんな感じ。
extern "C" {
 __declspec(dllexport) bool
 ReadValue(wchar_t* buffer, unsigned int bufferLength) {
  wcscpy_s(buffer, bufferLength, L"hogehoge");
  return true;
 }
}
それをこんなC#コードで呼び出すと、デバッグ実行時に pInvokeStackImbalance で怒られます。
[DllImport("foo.dll", CharSet = CharSet.Unicode)]
public static extern bool ReadValue(StringBuilder buffer, uint bufferLength);
MSDN: DllImportAttribute.CallingConvention フィールド によると
DllImportAttribute.CallingConvention の規定値は Winapi。
これはプラットフォーム標準の呼び出し規約を使用することを示す。Windows なら StdCall。
よくP/InvokeされるWin32APIの場合はすべてStdCallなので規定値でOKですね。

というわけで今回は次ように呼び出し規約をきちんと指定してあげないといけない。
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern bool ReadValue(
    StringBuilder buffer, uint bufferLength);
ちなみにこのエラーを検出している MDA (Managed Debugging Assistant) は、.NET Framework 3.5 では規定値で無効になっているらしいです。

0 件のコメント:

コメントを投稿