64bit Windows が本格的に普及する前にネイティブ DLL を P/Invoke する .NET アプリがやっておくべきこと
以前からいろいろ調べたり質問したりしてた、ネイティブ DLL を P/Invoke する .NET アプリを 64bit Windows でも動作させる方法がようやく納得できる形で見つかったので、備忘録を兼ねてメモしておく。
P/Invoke したいネイティブDLL
QA@ITでした質問
- .NET の動作プロセスについて - QA@IT http://bit.ly/Rxdb6B
- ターゲットCPUがAnyCPUではないアセンブリを、CPUに応じて動的にロードしたい - QA@IT http://bit.ly/Rxdbn5
参考にしたサイト
- Aqua Ware つぶやきブログ » System.Data.SQLite でどれをインストールするべきか http://bit.ly/VCfEwo
- SetDllDirectory function http://bit.ly/RxeDWN
なぜ必要か
まだまだ 32bit のサポートが必要だが、現在販売されている個人向けPCは 64bit 向けが大半を占めている。サーバーOSに至っては、 2008R2から 64bit しか用意されていない。
結論
- プロジェクトはターゲットプラットフォームを AnyCPU にする。
- x86用ネイティブDLLをx86ディレクトリに配置し、ビルドアクションを「コンテンツ」に設定する。さらに出力ディレクトリにコピーするようにしておく。
- x64用ネイティブDLLをx64ディレクトリに配置し、同様に設定する。
- SetDllDirectory でDLL検索パスを切り分ける。
using System; using System.IO; using System.Runtime.InteropServices; namespace Hoge { /// <summary> /// ネイティブDLLのロード先ディレクトリを追加するユーティリティクラスです。 /// </summary> public static class DllSearchPath { [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetDllDirectory(string lpPathName); /// <summary> /// ネイティブDLLのロード先ディレクトリを追加します。 /// </summary> /// <param name="path">ロード先ディレクトリ</param> public static void Add(string path) { SetDllDirectory(path); } /// <summary> /// x86とx64のネイティブDLLのロード先ディレクトリを追加します。 /// </summary> /// <param name="x86path">x86用ロード先ディレクトリ</param> /// <param name="x64path">x64用ロード先ディレクトリ</param> public static void Add(string x86path, string x64path) { int bitWidth = IntPtr.Size * 8; switch (bitWidth) { case 64: Add(x64path); break; case 32: Add(x86path); break; default: throw new NotSupportedException(); } } } } #Program.cs DllSearchPath.Add("path/to/x86", "path/to/x64");
ちなみに、 x86向けネイティブDLLしか用意されていない場合、ターゲットプラットフォームを x86 にしておく方が無難だろう。
動作原理
AnyCPU に設定しておけば、64bit Windows では 64bit プロセスとして動作し、32bit Windows では 32bit プロセスとして動作する。
DllSearchPath.Add で 32bit 向けパスと 64bit 向けパスをあらかじめ指定しておけば、自動的にプロセスを判断してロードするDLL
が配置されるディレクトリを決定してくれる。
System.Data.SQLite
参考URLにあるとおり、
- 32bit ・・・ Precompiled Statically-Linked Binaries for 32-bit Windows
- 64bit ・・・ Precompiled Statically-Linked Binaries for 64-bit Windows
をダウンロードしておけばいい。選定理由はこんな感じ。