将C结构移植到C#

时间:2013-04-17 16:14:06

标签: c# c pinvoke

我将C代码移植到C#,我有些疑惑。

考虑这个结构:

typedef struct
{
  uint32_t       w;
  uint32_t       h;
  uint32_t       f_cc;
  uint32_t       st;
  unsigned char *pl[4];
  int32_t        strd[4];
  void         (*done)(void *thisobj);
  void          *e_cc;
  uint32_t       rsrvd2;
  uint32_t       rsrvd3;
} f_tt;

我已经完成了这个并且它不起作用(可能是因为它错了: - /):

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct f_tt
{
    public uint w;
    public uint h;
    public uint f_cc;
    public uint st;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public Byte[] pl;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public int[] strd;
    public delegate void done(IntPtr thisobj);
    public delegate void e_cc();
    public uint rsrvd2;
    public uint rsrvd3;
}

有人可以告诉我如何做到这一点吗?

  void         (*done)(void *thisobj);
  void          *e_cc;

谢谢!

1 个答案:

答案 0 :(得分:4)

在我们来代表之前,我怀疑你打包结构是错误的。这样做非常不寻常。只有在C代码中找到包#pragma时才能这样做。

e_cc字段不是函数指针。它只是一个无效指针。在C#中IntPtr

pl成员是一个包含4个指针的数组。我不太确定它们包含什么,但肯定你可以像这样编组:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public IntPtr[] pl;

这会让您通过手动干预来填充数组或读取其内容。它可能由编组人员完成,但是如果不知道互操作的语义,我就不能说如何做到这一点。

对于done,您应该在结构外声明委托。像这样:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void doneDelegate(IntPtr thisobj);

这里我假设调用约定为cdecl,因为C代码中没有任何内容可以说明。

总而言之,你有:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void doneFunc(IntPtr thisobj);

[StructLayout(LayoutKind.Sequential)]
public struct f_tt
{
    public uint w;
    public uint h;
    public uint f_cc;
    public uint st;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public IntPtr[] pl;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public int[] strd;
    public doneDelegate done;
    public IntPtr e_cc;
    public uint rsrvd2;
    public uint rsrvd3;
}