将SAFEARRAY从C#传递给COM

时间:2010-05-19 08:04:48

标签: c# .net com interop

我使用第三方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 :(得分:0)

这类似于使用Marshal.AllocCoTaskMem初始化数组,然后使用Marshal.Copy将其复制到非托管内存,并将指向数组的IntPtr传递给COM方法。

一般情况下,请查看Marshal类:
http://msdn.microsoft.com/en-gb/library/system.runtime.interopservices.marshal.aspx

答案 1 :(得分:0)

哎呀,似乎只需要我来初始化数组,因为FacePosition2不是一个结构而是类,并且它没有自动初始化,因为我会这样做。这件作品遗失了:

for (var i = 0; i < facePositions.Length; i++)
{
  facePositions[i] = new FacePosition2();
}

答案 2 :(得分:0)

有更复杂的方法,但意见更正确: 改变这个签名Interop,所以,他看起来像是一个数组。

Accessing a SafeArray Result from a COM Call in C#

Default Marshaling for Arrays

Correcting Common Interop Assembly Problems