C# へのネイティブ DLL の取り込み - 値渡し,参照渡し引数編
仕事で C# を使うようになったため C# 関連の勉強を開始.既存の資産が C である場合が多いので,C の DLL を取り込む方法を調べた.
C# 側での記述
簡単な例 (参照渡しパラメータなしの Win32API)
DllImport 属性 (System.Runtime.InteropServices) を利用し,その関数が外部にあることを宣言する.例えば,下記の Win32API を用いる場合,,,
BOOL MessageBeep( UINT uType // サウンドの形式 );
C# 側では下記のように宣言する.
DllImport 属性をつけた Win32 API や DLL 関数の宣言では,関数の実体が外部にあることを表す extern 修飾子と静的なメンバであることを表す static を必ず指定する.
(Windows の DLL と .NET Framework とでは型の管理方法が異なるため,実際には型の相互変換(マーシャリング)が行われる.)
class BeepTest { // DLL "user32.dll" から持ってくる関数であることを宣言. [DllImport("user32.dll")] extern static bool MessageBeep(uint uType) public void test() { // 値渡しのパラメータを渡して呼んであげる. MessageBeep(0xFFFFFFFF); } static void Main() { BeepTest test = new BeepTest(); test.test(); } }
参照渡しのパラメータを含む DLL の場合
参照渡しのパラメータを含む関数を宣言するには,参照渡しになっているパラメータを ref パラメータとして宣言する.たとえば,例として下記のような関数を考えてみる.ここで,下記の関数は数字を受け取り,受け取った値に対して10追加して返す関数とする.
BOOL Add10( int* num // 参照渡しのパラメータ.関数呼び出し時に初期値の指定が必要で,関数が戻ってきたときの値も必要. );
上記のような参照渡しのパラメータを含む DLL 関数の場合,C# 側では下記のように宣言する.
// 呼び出し側から初期値を与える必要がない場合は,"ref" を "out" として宣言することもできる. class AddTest { [DllImport("MyDll.dll")] extern static bool Add10(ref uint num); public void test() { int num = 3; Console.WriteLine("Original Number : " + num); Add10(ref num); // 関数呼び出し側でも参照変数であることを明示. Console.WriteLine("Modified Number : " + num); Console.ReadLine(); } static void Main() { test(); } }
一方で,関数の提供側である C のコードは下記のように記述する.
// MyDll.h extern "C" { __declspec(dllexport) void Add10(int* num); } // MyDll.cpp void Add10(int* num) { *num = *num + 10; return; }