C#でアンマネージな関数を使いたければ、DllImportを使うのが常道です。しかし、定義の際に必ずstaticをつけることからもわかるように、静的な定義であり、プログラムの実行中に動的に関数名を決めてロード、といったことはできません。
C/C++ではWin32APIのLoadLibraryとGetProcAddressを使って得た関数ポインタで関数を呼び出すことができます。そこでC#でも同じ方法を使ってみましょう。
// デリゲートの定義 delegate IntPtr LoadImageDelegate(string filename, int flags); delegate int SaveImageDelegate(string filename, IntPtr img); [DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [DllImport("kernel32.dll")] static extern bool FreeLibrary(IntPtr hLibModule); static void Main(string[] args) { // 関数ポインタを取得 IntPtr ptrLib = LoadLibrary("highgui110.dll"); IntPtr ptrLoad = GetProcAddress(ptrLib, "cvLoadImage"); IntPtr ptrSave = GetProcAddress(ptrLib, "cvSaveImage"); // 関数ポインタをデリゲートに変換する LoadImageDelegate loadDelegate = (LoadImageDelegate)Marshal.GetDelegateForFunctionPointer(ptrLoad, typeof(LoadImageDelegate)); SaveImageDelegate saveDelegate = (SaveImageDelegate)Marshal.GetDelegateForFunctionPointer(ptrSave, typeof(SaveImageDelegate)); // デリゲートを呼び出す IntPtr img = loadDelegate("hoge.jpg", 1); saveDelegate("fuga.png", img); // ライブラリを解放 FreeLibrary(ptrLib); }
こんな感じでMarshal.GetDelegateForFunctionPointerを使うことで関数ポインタをデリゲートに変換して呼び出すことができます。せっかくなのでこの機能をOpenCvSharpに組み込んでみました。ラップしてないのを使いたいという場合の急場しのぎに使える・・・かも。
delegate int SaveImageDelegate(String filename, IntPtr img); static void Main(string[] args) { IplImage img = new IplImage("lenna.jpg"); using (var invoker = new DynamicInvoker<SaveImageDelegate>("highgui110.dll", "cvSaveImage")) { invoker.Call("lenna.bmp", img.CvPtr); } }
C#とOpenCVの融合プログラミング―ライブラリのラッパーDLLを利用する
- 作者: 北山洋幸
- 出版社/メーカー: カットシステム
- 発売日: 2010/11
- メディア: 単行本
- クリック: 21回
- この商品を含むブログ (3件) を見る