Passing SAFEARRAY from C # to COM

I am using 3rd party COM to find faces in a picture. One of the methods has the following signature from the SDK:

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

      

Parameters: pIDibImage [in] - Image for search.

FacePositionArray [out] - an array of FacePosition2 Objects into which the information is placed. This array is in a safe array (VARIANT) of type VT_UNKNOWN. The size of the array dictates the maximum number of faces to search.

which translates to the following C # method signature (from metadata):

int FindMultipleFaces(object pIDibImage, ref object pIFacePositions);

      

Being an optimist, I call it like this, but I get an exception that the memory is corrupted. An exception is thrown only if 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 correct way to pass SAFEARRAY to unmanaged code?

+2


a source to share


3 answers


Unfortunately it seems to me that I only need to initialize the array because FacePosition2 was not a struct class, but it did not automatically initialize as I would. This snippet was missing:



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

      

0


a source


Something like initializing an array with Marshal.AllocCoTaskMem

, then use Marshal.Copy

to copy it into unmanaged memory and pass a a IntPtr

pointing to the array in a COM method.



In general, take a look at the class Marshal

:
http://msdn.microsoft.com/en-gb/library/system.runtime.interopservices.marshal.aspx

0


a source


There is a more complex method, but the opinion is more correct: change this Interop signature so that it looks like an array.

Accessing SafeArray result from COM call in C #

Default Marshaling for Arrays

Fixing assembly build issues in general

0


a source







All Articles