P/Invoke を使用して、いくつかの C++ DLL からアンマネージ関数を呼び出すコードに取り組んでいます。アプリケーションを 32 ビットまたは 64 ビットとしてビルドできるようにしたいと考えています。
現在、x86 としてのみ動作します。
参照されている C++ DLL のそれぞれの 32 ビットと 64 ビットのコピーがあり、次のコードを使用して、アプリが x86 または x64 としてビルドされているかどうかに応じて DllDirectory を変更しています (/lib/x64 は 64 ビット DLL、/lib/ を保持します)。 x86 は 32 ビットのものを保持します):
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern bool SetDllDirectory(string lpPathName);
string libPath = Path.Combine(Environment.CurrentDirectory, "lib", (Environment.Is64BitProcess == true ? "x64" : "x86"));
SetDllDirectory(libPath);
残りのアンマネージ C++ 関数は次のように定義されています。
[DllImport("libgobject-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void g_type_init();
[DllImport("libgobject-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void g_object_unref(IntPtr pixbuf);
[DllImport("librsvg-2-2.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern IntPtr rsvg_pixbuf_from_file_at_size(string file_name, int width, int height, out IntPtr error);
[DllImport("libgdk_pixbuf-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern bool gdk_pixbuf_save(IntPtr pixbuf, string filename, string type, out IntPtr error, __arglist);
これらの関数を実際に使用するコードは次のようになります。
g_type_init();
IntPtr ptrError;
IntPtr ptrPixbuf = rsvg_pixbuf_from_file_at_size(filePath, width, height, out ptrError);
if (ptrError == IntPtr.Zero)
{
bool isSaved = gdk_pixbuf_save(ptrPixbuf, outputPath, outputFormat, out ptrError, __arglist(null)); //this line fails when compiled as x64!
if (isSaved && File.Exists(outputPath))
{
return outputPath;
}
}
g_object_unref(ptrPixbuf);
前述したように、アプリケーションをローカル マシン (Windows 7 x64) で x86 として実行すると、すべて正常に動作します。ただし、x64 アプリケーションとしてコンパイルすると、gdk_pixbuf_save() の呼び出しで「AccessViolationException」が発生します。
何か案は?私は相互運用コードに比較的慣れていませんが、IntPtr 変数がアンマネージ コードとの間で送受信される方法に関係があると思いますか? しかし、x86 と x64 ではなぜ違うのでしょうか?