我将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;
谢谢!
答案 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;
}