Как правильно передать массив C в C#? - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь передать некоторые массивы из 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);

Это скомпилировано и, похоже, работает нормально, пока Я заметил, что он возвращает только первый элемент каждого массива! и поскольку длина больше, чем размеры массива, программа выдаст sh с ошибкой индекса вне диапазона.

Затем я попытался изменить их на:

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

как предложено в аналогичном вопросе здесь , но это тоже не повлияло. По-прежнему возвращается только первый элемент. Что мне здесь не хватает?

1 Ответ

2 голосов
/ 26 мая 2020

Маршаллеру необходимо знать, сколько элементов имеет неуправляемый массив. Сам массив не содержит этой информации.

Обратный вызов сообщает вам, сколько элементов содержится в 5-м аргументе int length, который имеет отсчитываемый от нуля индекс 4. Итак, скажет упаковщику использовать эту информацию:

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