我正在尝试将某些数组从C ++传递给C#,它们作为C数组公开。这些数组是使用C#中的回调接收的。这是它们在C ++端的定义方式:
struct Image
{
unsigned char* image_ptr;
int rows;
int cols;
};
typedef void(*CCallbackFn)(bool[], const char* [], Image[], Image, int length);
这就是我在C#中公开它们的方式:
[StructLayout(LayoutKind.Sequential)]
struct ImageStruct
{
public IntPtr image_ptr;
public int rows;
public int cols;
}
delegate void CallbackDelegate( bool[] status, string[] id, ImageStruct[] img_face, ImageStruct img_org, int length);
经过编译,看起来似乎很好,直到我注意到它仅返回每个数组的第一个元素!并且由于长度大于数组大小,程序将因索引超出范围错误而崩溃。
然后我尝试将它们更改为:
delegate void CallbackDelegate([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] bool[] status,
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string[] id,
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPArray)] ImageStruct[] img_face,
ImageStruct img_org, int length);
[在类似问题here中建议,但也没有任何作用。仍然只返回第一个元素。我在这里想念什么?
封送拆收器需要知道非托管数组有多少个元素。数组本身不包含此信息。
回调告诉您第5个参数int length
中有多少个元素,该参数具有从零开始的索引4
。因此,tell封送处理程序可以使用此信息:
delegate void CallbackDelegate(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 4)] bool[] status,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 4)] string[] id,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] ImageStruct[] img_face,
ImageStruct img_org,
int length
);