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

标签 c# c pinvoke

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

PixelIterator NewPixelRegionIterator(MagickWand *wand,const ssize_t x,
const ssize_t y,const size_t width,const size_t height)

下面是将这个函数导入到 C# 代码中的代码:

[DllImport("libMagickWandDev.so")]
internal static extern PixelIterator NewPixelRegionIterator(IntPtr MagickWand,  
          IntPtr left, IntPtr top, UIntPtr width, UIntPtr height);

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

通过gdb发现问题是在调用NewPixelRegionIterator时如:

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)。这意味着参数的顺序有点向右移动,并且 0x7fffffffc7a8 可能是要返回的结构或其他内容的一部分。
  • 如果有帮助,10744336MagickWandPtr 的值(魔棒的地址),因为将 wand 参数设置为此在 gdb 中将 x 设置为正常值可以使函数运行良好。
  • PixelIterator 是一个映射得非常仔细的结构体(我还通过 Marshal.SizeOf 验证了该结构体的大小和实际 C 代码的 sizeof() 是相同的 4192 字节)

再次提前致谢。

最佳答案

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

由于参数发生了偏移,我希望将 PixelIterator* 类型的隐藏参数作为第一个或最后一个参数。以及 void 的返回类型。这就是 C 编译器在底层实现结构返回函数的方式。

在评论中,您解释说返回 PixelIterator* 可以解决问题。原因可能是 C 函数正在分配一个对象并返回其指针。不过,定义并没有给出任何线索...无论如何,当您完成返回的对象时,您可能需要释放该内存。

关于c# - P/Invoke 传递给 C 库函数的参数错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10049224/

相关文章:

c# - 在传递给非托管代码之前将委托(delegate)固定在结构中

C# 将变量复制到缓冲区而不产生垃圾?

c# - 在构建之后/之前将文件复制到 AppData\Roaming

c - UART ISR Tx Rx 架构

将 Windows 设备文件名转换为驱动器号

c# - P/Invoke Struct with Pointers, C++ 从 C#

c# - NHibernate 删除我的行

c# - 类型化工厂静默丢弃无法映射到构造函数的参数?

c - 如何用整数中的任意位替换/覆盖短数组中任意位置的任意数量的位

c# - WindowsIdentity 构造函数使用 LogonUser 的 token 引发异常