简体   繁体   English

将SAFEARRAY从C#传递到COM

[英]Passing a SAFEARRAY from C# to COM

I use 3rd party COM to find faces in a picture. 我使用第三方COM在图片中查找人脸。 One of the methods has the following signature, from SDK: 其中一种方法具有来自SDK的以下签名:

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

Parameters: pIDibImage[in] - The image to search. 参数:pIDibImage [in]-要搜索的图像。

FacePositionArray[out]- The array of FacePosition2 objects into which face information is placed. FacePositionArray [out]-放置面部信息的FacePosition2对象的数组。 This array is in a safe array (VARIANT) of type VT_UNKNOWN. 该数组位于VT_UNKNOWN类型的安全数组(VARIANT)中。 The size of the array dictates the maximum number of faces for which to search. 数组的大小决定了要搜索的面孔的最大数量。

which translates into the following C# method signature (from metadata): 转换为以下C#方法签名(来自元数据):

int FindMultipleFaces(object pIDibImage, ref object pIFacePositions);

Being optimistic I call it the following way but get an exception that the memory is corrupt. 乐观的是,我用以下方式称呼它,但是却发现内存已损坏。 The exception is thrown only when a face is present in the image. 仅当图像中有面部时才引发异常。

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

What's the right way to pass SAFEARRAY to unmanaged code? 将SAFEARRAY传递给非托管代码的正确方法是什么?

It's something like you initialize an array using Marshal.AllocCoTaskMem and then use Marshal.Copy to copy it to unmanaged memory and the pass an IntPtr pointing to the array into the COM method. 就像您使用Marshal.AllocCoTaskMem初始化数组,然后使用Marshal.Copy将其复制到非托管内存,然后将指向该数组的IntPtr传递到COM方法中。

In general, look at the Marshal class: 通常,请看Marshal课:
http://msdn.microsoft.com/en-gb/library/system.runtime.interopservices.marshal.aspx http://msdn.microsoft.com/zh-CN/library/system.runtime.interopservices.marshal.aspx

Oops, it seems it only needed from me to initialize the array because FacePosition2 was not a struct but class and it was not initialized automatically as I though it would. 糟糕,似乎只需要我初始化数组即可,因为FacePosition2不是结构而是类,并且不会像我那样自动初始化。 This piece was missing: 这部分丢失了:

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

There are more sophisticated method, but opinion is more correct: change this signature Interop, so, he looks like taking an array. 有更复杂的方法,但意见更正确:更改此签名Interop,因此,他看起来像在处理数组。

Accessing a SafeArray Result from a COM Call in C# 通过C#中的COM调用访问SafeArray结果

Default Marshaling for Arrays 数组的默认封送处理

Correcting Common Interop Assembly Problems 更正常见的互操作程序集问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM