如何正确地将 C 数组传递给 C#?

How to properly pass a C array to C#?

我正在尝试将一些数组从 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);

编译后似乎工作正常,直到我注意到它只 returns 每个数组的第一个元素!由于长度大于数组大小,程序将因索引超出范围错误而崩溃。

然后我尝试将它们更改为:

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);

如类似问题 中所建议,但这也没有任何效果。仍然只返回第一个元素。我在这里错过了什么?

编组器需要知道非托管数组有多少个元素。数组本身不包含此信息。

回调告诉您第 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
);