我正在处理一些涉及使用 P/Invoke 从几个 C++ DLL 调用非托管函数的代码。我希望能够将应用程序构建为 32 位或 64 位。
目前,它仅适用于 x86。
我有每个引用的 C++ DLL 的 32 位和 64 位副本,并且正在使用以下代码来更改 DllDirectory,具体取决于应用程序是构建为 x86 还是 x64(/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 不同呢?