Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.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
C# P/Invoke传递给C库函数的参数错误_C#_C_Pinvoke - Fatal编程技术网

C# P/Invoke传递给C库函数的参数错误

C# P/Invoke传递给C库函数的参数错误,c#,c,pinvoke,C#,C,Pinvoke,我一直试图从C#代码调用ImageMagick库中的NewPixelRegionitor函数,但遇到了参数传递问题。 更具体地说,以下是NewPixelRegionitor的定义: PixelIterator NewPixelRegionIterator(MagickWand *wand,const ssize_t x, const ssize_t y,const size_t width,const size_t height) 下面是将此函数导入C代码的代码: 我导入libMagickWa

我一直试图从C#代码调用ImageMagick库中的NewPixelRegionitor函数,但遇到了参数传递问题。
更具体地说,以下是NewPixelRegionitor的定义:

PixelIterator NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
const ssize_t y,const size_t width,const size_t height)
下面是将此函数导入C代码的代码:

我导入libMagickWandDev.so而不是libMagickWand.so是因为libMagickWandDev.so是在启用调试支持的情况下编译的,因此我可以使用gdb运行mono,以了解问题是否出在对C函数的调用中(事实上确实如此)

通过gdb发现的问题是,当调用NewPixelRegionitor时,例如:

PixelIterator PixIt = PixelIteratorImports.NewPixelRegionIterator(MagickWandPtr,  
         new IntPtr(x), new IntPtr(y), new UIntPtr(1), new UIntPtr(1));
通过gdb传递的实际参数包括:

Breakpoint 1, NewPixelRegionIterator (wand=0x7fffffffc7a8, x=10744336, y=5, 
width=6, height=1) at wand/pixel-iterator.c:418
  • 5和6很好,这是传递给函数的实际数字(虽然x应该等于5,y应该等于6,使宽度和高度都等于1)。这意味着参数的顺序有点向右移动,0x7FFFFFC7A8可能是要返回的结构的一部分或其他内容
  • 如果有帮助的话,10744336是MagickWandPtr(Magick魔杖的地址)的值,因为在gdb中将魔杖参数设置为this,将x设置为sane值,可以使函数正常运行
  • PixelIterator是一个经过仔细映射的结构(我还通过Marshal.SizeOf和实际C代码的SizeOf()验证了结构的大小是相同的4192字节)

再一次,提前感谢。

您确定可以从PInvoke函数返回结构吗?您不需要使用out参数/指针返回它吗

因为参数是移位的,所以我希望第一个或最后一个参数是PixelIterator*类型的隐藏参数。和返回类型的void。这就是C编译器在后台实现结构返回函数的方式


在评论中,您解释了返回像素迭代器*可以解决问题。原因可能是C函数正在分配一个对象并返回其指针。这个定义没有给出一个线索,但是。。。无论如何,处理完返回的对象后,可能需要释放内存。

检查C api使用的调用转换。您最可能的选择是Cdecl或stdcall。DllImportAttribute的默认值是WinApi,它将默认为对除Win CE以外的任何对象调用stcall。是否确实可以从PInvoke函数返回结构?您不需要使用out参数/指针返回它吗?我想部分问题在于
size\t
。。。它可能是32位,但您要传递的是IntPtr,在64位系统上是64位。(还有,为什么对某些参数使用UIntPtr,而对其他参数使用IntPtr呢?)但想想看,这些值被推到了右边,所以可能是调用了一个带有64位指针的32位函数?请尝试在32位进程中运行整个过程。谢谢@user957902,我使用的是Mono linux,Cdecl和StdCall仍然无法工作。@phoog我已经编写了一个C程序,可以打印sizeof(size_t)和sizeof(ssize_t),它们在我的机器中都有8个字节长。此外,ssize_it是有符号的,size_t是无符号的,这就是为什么我在C#中使用模拟类型(尽管我不太在意,因为这些值通常非常小)。我在一台64位机器上编译了ImageMagick,因此我希望它是一个64位库,尽管它不可能是。现在我将尝试在32位模式下运行我的程序。我不知道C编译器在这方面的行为。我已经更改了导入代码,将“out IntPtr ReturnValue”作为第一个参数,并将其设置为void return类型,但参数的传递仍然不正确。您是否知道有来源更详细地解释了如何执行此操作?您是否尝试将此参数添加为最后一个参数?同时尝试在列表的开头和结尾添加1-2个padding参数。仍然按照您对C函数实际返回指针的想法,我想也许我应该只给导入的方法一个IntPtr返回类型,而不包括任何其他参数。看来你是对的!在将指针指向的值转换为结构后,我成功地访问了它的成员。。如果你能修改一下你的答案,我会给你正确的答案。
Breakpoint 1, NewPixelRegionIterator (wand=0x7fffffffc7a8, x=10744336, y=5, 
width=6, height=1) at wand/pixel-iterator.c:418