yohhoyの日記

技術的メモをしていきたい日記

P/Invokeの呼び出し規約+文字セット指定

C#からのP/Invokeにおける関数呼び出し規約、文字セット(MBCS/UNICODE)の指定方法についてメモ。

P/Invoke既定の呼び出し規約はCallingConvention.StdCallとなっており、アンマネージド側が__stdcallならば明示指定は必須でははない。*1
P/Invoke既定の文字セットはCharSet.Ansiとなっており、アンマネージド側が マルチバイト文字セット(MBCS) であれば必ずしも明示指定する必要は無い。

// foo.dll (C)
int WINAPI BarFuncA(LPCSTR a1) { /*...*/ }
int CALLBACK ZotCallbackW(LPCWSTR a1);  // placeholder
// caller_foo.cs (C#)
using System.Runtime.InteropServices;

[DllImport("foo.dll", EntryPoint="BarFuncA", CharSet=CharSet.Ansi)]
extern int BarFunc([In] string a1);

[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet=CharSet.Unicode)]
delegate int ZotDelegate([In] string a1);

Windows SDKで定義される関数呼び出し規約は下記の通り。また、x86コンパイラ既定の呼び出し規約は __cdeclとなっており*2、この場合はマネージド側には CallingConvention.Cdeclを明示指定する。

// WinDef.h
#define WINAPI    __stdcall
#define CALLBACK  __stdcall
#define APIENTRY  WINAPI

関連URL

*1:後述サンプルではデリゲートで CharSet 指定を行うため、UnmanagedFunctionPointer 属性引数で指定している。

*2:Microsoft Visual C++では __cdecl が既定値だが、コンパイルオプションで変更されている場合もある。