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?
a source to share
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();
}
a source to share
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
a source to share
There is a more complex method, but the opinion is more correct: change this Interop signature so that it looks like an array.
a source to share