Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用P/Invoke调用64位C++;来自64位C#应用程序的DLL? 我正在研究一些代码,涉及使用p/VoCKE从几个C++ DLL调用非托管函数。我希望能够将应用程序构建为32位或64位_C#_C++_Pinvoke_Gdkpixbuf - Fatal编程技术网

如何使用P/Invoke调用64位C++;来自64位C#应用程序的DLL? 我正在研究一些代码,涉及使用p/VoCKE从几个C++ DLL调用非托管函数。我希望能够将应用程序构建为32位或64位

如何使用P/Invoke调用64位C++;来自64位C#应用程序的DLL? 我正在研究一些代码,涉及使用p/VoCKE从几个C++ DLL调用非托管函数。我希望能够将应用程序构建为32位或64位,c#,c++,pinvoke,gdkpixbuf,C#,C++,Pinvoke,Gdkpixbuf,目前,它只能作为x86使用 每个引用的C++ DLL都有32个和64位副本,AM使用以下代码来更改DLL目录,这取决于应用程序是以x86还是x64(/LIb/x64保存64位DLL,/LIb/x86保存32位DLL): 我的非托管C++函数的其余部分定义如下: [DllImport("libgobject-2.0-0.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] static extern

目前,它只能作为x86使用

每个引用的C++ DLL都有32个和64位副本,AM使用以下代码来更改DLL目录,这取决于应用程序是以x86还是x64(/LIb/x64保存64位DLL,/LIb/x86保存32位DLL): <>我的非托管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);
正如我所提到的,在本地计算机(Windows7x64)上以x86运行应用程序时,一切正常。但是,当我将其编译为x64应用程序时,在调用gdk_pixbuf_save()时会得到一个“AccessViolationException”


有什么想法吗?我对互操作代码比较陌生,但我认为这可能与IntPtr变量如何发送到非托管代码有关?但是为什么它与x86到x64不同呢?

非常感谢所有发表评论的人——你们让我走上了正确的道路,并帮助我解决了一个潜在的问题

最初,我希望有一个x64版本,以备不时之需……结果就是这样

事实证明,他们是正确的。在x64版本上,未记录的
\uuuuuuu arglist
关键字无法正常工作

具体来说,我不能评论出了什么问题。我链接的评论提到了调用约定设置不正确的可能性。我不知道这是怎么回事…x64不是只有一个呼叫约定吗

不管怎样,回到正题:

我将我的
DllImport
更改为
gdk\u pixbuf\u save
如下所示:

[DllImport("libgdk_pixbuf-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool gdk_pixbuf_save(UIntPtr pixbuf, string filename, string type, out UIntPtr error, UIntPtr arglist);
bool isSaved = gdk_pixbuf_save(ptrPixbuf, outputFilePath, outputFileFormat, out ptrError, UIntPtr.Zero);
这里的关键是我将最后一个参数,
arglist
作为
IntPtr
传递,而不是
\uuuu arglist

实际上,我将它作为
UIntPtr
传递,因为我将所有原始
IntPtr
对象切换到
UIntPtr

也就是说,当我调用函数时,它看起来是这样的:

[DllImport("libgdk_pixbuf-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool gdk_pixbuf_save(UIntPtr pixbuf, string filename, string type, out UIntPtr error, UIntPtr arglist);
bool isSaved = gdk_pixbuf_save(ptrPixbuf, outputFilePath, outputFileFormat, out ptrError, UIntPtr.Zero);
由于我的
\uuuuu arglist
为空(可以指定其他可选参数),因此告诉我应该以null结尾。为了实现这一点,我传入了
IntPtr.Zero
(在我的例子中是
uintpr.Zero

现在,我的代码可以编译、运行,我(更重要的是)可以访问64位的内存


再次感谢那些对我的帖子发表评论的人——如果没有你指向
\uuuuu arglist
参数的指针,我会完全不知所措。

你必须调试它,这样你至少可以知道哪个参数是错误的。在本地C++代码上设置断点并从中获取它。这需要C++/CLI。我只使用了
\uuuuuu arglist
,因为我发现的一个示例就是这样使用的。也就是说,我尝试从函数调用中删除它,得到了相同的结果:它在32位构建上成功,在64位构建上失败。而且,我真的没有访问本机C++代码的权限。我的意思是,这是一个Gnome库,所以它是可用的,但我根本没有在Windows中调试它。做得好!旁白:在调用任何其他Pinvoke之前,您可以使用DLL的完整路径调用LoadLibrary,而不是使用SetDllDirectory。只是另一种方法。