Передача SAFEARRAY из C # в COM - PullRequest
2 голосов
/ 19 мая 2010

Я использую сторонний COM, чтобы найти лица на картинке. Один из методов имеет следующую сигнатуру из SDK:

long FindMultipleFaces(
  IUnknown* pIDibImage,
  VARIANTARG* FacePositionArray
);

Параметры: pIDibImage [in] - Изображение искать.

FacePositionArray [out] - Массив FacePosition2 объекты, в которые лицо информация размещена. Этот массив в безопасном массиве (VARIANT) типа VT_UNKNOWN. Размер массива диктует максимальное количество лиц для которого искать.

, что переводится в следующую сигнатуру метода C # (из метаданных):

int FindMultipleFaces(object pIDibImage, ref object pIFacePositions);

Будучи оптимистом, я называю это следующим образом, но получаю исключение, что память повреждена. Исключение выдается, только если на изображении присутствует лицо.

FacePosition2[] facePositions = new FacePosition2[10];
object positions = facePositions;
int faceCount = FaceLocator.FindMultipleFaces(dibImage, ref positions);

Как правильно передать SAFEARRAY в неуправляемый код?

Ответы [ 3 ]

0 голосов
/ 19 мая 2010

Ой, кажется, мне нужно было только инициализировать массив, потому что FacePosition2 был не структурой, а классом, и он не был инициализирован автоматически, как я думал. Этот кусок отсутствовал:

for (var i = 0; i < facePositions.Length; i++)
{
  facePositions[i] = new FacePosition2();
}
0 голосов
/ 19 мая 2010

Есть более изощренный метод, но мнение более правильное: измените эту подпись Interop, поэтому он выглядит как массив.

Доступ к результату SafeArray из COM-вызова в C #

Маршалинг по умолчанию для массивов

Устранение общих проблем сборки взаимодействия

0 голосов
/ 19 мая 2010

Это что-то вроде инициализации массива с использованием Marshal.AllocCoTaskMem, а затем использования Marshal.Copy для копирования его в неуправляемую память и передачи IntPtr, указывающего на массив, в метод COM.

В общем, посмотрите на Marshal класс:
http://msdn.microsoft.com/en-gb/library/system.runtime.interopservices.marshal.aspx

...