I want to pass some image data from C# code to unmanaged C++ using ATL/COM
From C# code side i do something like this:
void SendFrame([In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_UI1)] ref byte[] frameData);
But I'm not sure how should I handle this function in my C++ code.
For now I have something like this:
_ATL_FUNC_INFO OnSendFrameDef = { CC_STDCALL, VT_EMPTY, 1, { VT_SAFEARRAY | VT_UI1 } };
void __stdcall OnSendFrame(SAFEARRAY* ppData)
{
BYTE* pData;
SafeArrayAccessData(ppData, (void **) &pData);
// Doing some stuff with my pData
SafeArrayUnaccessData(ppData);
}
Can anyone give me some suggestions how I can make this thing work?
Thanks.
I've managed to achieve my goal! For those who are interested:
My event handler descriptor looks like this:
_ATL_FUNC_INFO Stream::OnStreamFrameCallbackDef = { CC_STDCALL, VT_EMPTY, 1, { VT_DISPATCH } };
My C++ function:
void __stdcall Stream::OnStreamFrameCallback(IDispatch* pFrame)
{
// NOTE that this "IStreamFramePtr" is COM's Ptr of my "IStreamFrame"
MyCOM::IStreamFramePtr pStreamFrame = pFrame;
// Thanks casperOne♦ for this:
CComSafeArray<byte> array;
array.Attach(pStreamFrame->GetBuffer());
// Now I can do stuff that I need...
byte* pBuffer = &array.GetAt(0);
}
My "IStreamFrame" in my .tlh file looks like this:
struct __declspec(uuid("1f6efffc-0ac7-3221-8175-5272a09cea82"))
IStreamFrame : IDispatch
{
__declspec(property(get=GetWidth))
long Width;
__declspec(property(get=GetHeight))
long Height;
__declspec(property(get=GetBuffer))
SAFEARRAY * Buffer;
long GetWidth ( );
long GetHeight ( );
SAFEARRAY * GetBuffer ( );
};
In my C# code I have something like this:
[ComVisible(true)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface IStreamFrame
{
int Width { [return: MarshalAs(UnmanagedType.I4)] get; }
int Height { [return: MarshalAs(UnmanagedType.I4)] get; }
byte[] Buffer { [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_UI1)] get; }
};
[ComVisible(false)]
public delegate void StreamFrameCallback(IStreamFrame frame);
[ComVisible(true)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyCOMStreamEvents
{
[DispId(1)]
void OnStreamFrameCallback([In, MarshalAs(UnmanagedType.IDispatch)] IStreamFrame frame);
}
Things seems to work just fine. But if anyone have any suggestions or noticed that I'm doing something wrong please let me know.
Thanks.