64bitWindows + C# でDLLが読み込めない。
結構はまったのでメモ。
64biWindowsを利用している場合、32bit設定でビルドされたDLLは読み込むことができません。
// hoge32.dll内にある、void HogeFunc()をインポートして、delegateに格納する例。 [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32", SetLastError = true)] internal static extern bool FreeLibrary(IntPtr hModule); [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)] internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); // private delegate void HogeFunc(); // private void button1_Click(object sender, EventArgs e) { // DLLを読み込む。 IntPtr handle = LoadLibrary("hoge32.dll"); if (handle == null) { // 64bitOSで32bitビルドのDLLを読み込んだ場合、ここでresult == 193が返ってくる。 int result = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); System.Diagnostics.Debug.WriteLine(result); } IntPtr funcPtr = GetProcAddress(handle, "HogeFunc"); // // HogeFunc hogefunc = (hogefunc)System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(hogefunc)); hogefunc(); FreeLibrary(handle); }
しかし、C#のデフォルト設定では「Any CPU」に設定されており、動作するWindowsのバージョンにあわせて64/32bitのアプリケーション側で切り替えるようにビルドします。ある意味賢い。
しかし、そうなると64bit環境で動かす場合、DLLが読み込めなくなってしまいます。
これを何とかするには、以下の二つの方法があります。
- DLLを64bit環境でビルドしなおす。
- ビルド設定で切り替え機能を無効にし、32bitアプリケーションとして実行するように変更する。
- ビルド後のアプリケーションの設定を変更して、32bitアプリケーションとして実行するように変更する。
DLLをリビルドできる環境であれば、1.を試すべきですが、あいにく今回は取れない(Susieプラグインを読み込みたい)。
というわけで、2.を試してみたのですが、メニューのどこを見渡しても32/64bitのビルド切り替えが見つからない。
これは、デフォルト設定では隠しメニューなので出てこないのです。
やり方は(VC#2008で説明します)、
- Visual C# のメニューからツール->オプションを選択。
- 左下の「すべての設定を表示」にチェックを入れる。
- オプションダイアログの左のツリーから「プロジェクトおよびソリューション」の「全般」を選択。
- 「ビルド構成の詳細を表示」にチェックを入れる。
- これでCPUが選択できます。VisualC#のメニューから「ビルド->構成マネージャ」
- 「アクティブソリューションプラットフォーム」のコンボボックスから「新規作成」を選択。
- 「新しいプラットフォームを入力または選択してください」のドロップボックスからx86を選択。設定のコピー元は「Any CPU」を選択してOKを押す。
- あとはそのままビルド。32bit DLLの関数も実行できるはずです。