|
分類:[C#]
お世話になります。
C#のバージョンは2010 / .NET Framework は4.0で、プラットフォームは x86 です。
C言語DLL側はWin32DLL(32bitのみ)です。
C言語で作成されたDLL内のAPIを呼び出しています。
このAPIにはコールバック関数を引数として渡す必要があります。
このコールバック関数のマーシャリングについて御知恵をお借りしたいです。
(特にSizeParamIndexについて)
C言語DLL側宣言
typedef BOOL (__stdcall *MyCallback)(LPCWSTR myMessage, BYTE* myData, unsigned int dataSize);
BOOL __stdcall MyAPI(MyCallback callBack);
myMessageは内容を変更不能なUNICODEヌル終端文字列です。
myDataは、内容を変更不能なバイト配列の先頭アドレスで、配列の要素数は引数dataSizeで示されます。
C#側宣言
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool MyCallback(
[MarshalAs(UnmanagedType.LPWStr)] string myMessage,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] myData,
uint dataSize);
[DllImport("MyAPIs.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern BOOL MyAPI(MyCallback callBack);
myMessageはUNICODEヌル終端文字列なので、[MarshalAs(UnmanagedType.LPWStr)]を指定した
string型で受けています。
myDataは引数dataSizeで長さが規定されるバイト配列の先頭アドレスなので、
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] を指定したbyte配列です。
UnmanagedType.LPArrayでC言語側の実体が配列であること、SizeParamIndex = 2でこの
配列の要素数を示すのが2番め(先頭=0)の引数であることを指定しています。
また、API、コールバック関数共に戻り値はWin32のBOOL(4バイト)なので、それを指定する
ために[return: MarshalAs(UnmanagedType.Bool)]をそれぞれに付加しています。
これで正常に動作しているのですが、コールバック関数のC#的にはdataSize引数が冗長なので
可能であれば省きたいのです。
単純に考えると上記delegateはprivateとしてAPIからのコールバックを受け、C#側に公開する
ためのdataSize引数を省いたdelegateをpublicで用意すれば良さそうです。
が、これだと二段階の呼び出しになってしまうので、もっと単純に一発でdataSize引数を省く
方法があればそれを使いたいのです。
自分で調べた限りでは見つけられなかったのですが、もし方法があればご教示いただけると嬉
しいです。
または、こんな方法では全然ダメでもっとスマートな方法があるのであれば、ご指摘いただけ
るととても嬉しいです。
以上、よろしくお願いします。
|