I am trying to pass an array of UINT32
from a C# client to C++ ATL COM service.
The IDL
declaration is:
[propput, id(1)] HRESULT ThingyData([in] SAFEARRAY(UINT32) newVal);
The C# code that calls it is:
thingy.ThingyData = new UInt32[] { (UInt32)1 }.ToArray();
The C++ implementation is:
STDMETHODIMP CThingy::put_ThingyData(SAFEARRAY * newVal)
{
CComSafeArray<UINT32> sa;
sa.CopyFrom(newVal); //fails here
//... do some other stuff ...
return S_OK;
}
The code fails at sa.CopyFrom(...)
, returning E_INVALIDARG
. I debug into the CopyFrom
function:
HRESULT CopyFrom(_In_ const SAFEARRAY *psaSrc)
{
ATLENSURE_THROW(psaSrc != NULL, E_INVALIDARG);
VARTYPE vt;
HRESULT hRes = ::ATL::AtlSafeArrayGetActualVartype(const_cast<LPSAFEARRAY>(psaSrc), &vt);
ATLENSURE_SUCCEEDED(hRes);
ATLENSURE_THROW(vt == GetType(), E_INVALIDARG);
// ...
}
Where it fails at the second ATLENSURE_THROW
because vt == 23 (VT_UINT)
and GetType()
returns 19 (VT_UI4)
.
My code is running in 32-bit so this should not really be a problem. After more digging I find I can explicitly declare the CComSafeArray
to use VT_UINT
:
CComSafeArray<UINT32, VT_UINT> sa;
This works, surprisingly. But I am not sure if this is the right way to go about things. Would there be issues with portability, or other weird side effects? I think I read somewhere using VT_UINT
in COM is not recommended. What I would prefer is a way to get C# to send the array with VT_UI4
type; is that possible?
Thanks a lot. Trying to wrap my head around all this COM stuff.