How to return String-Arrays from C++ COM component to C#?
Want to return an array of strings from native COM component to managed code?
You need to declare the string array as SAFEARRAY(VARIANT) in the COM code.
IDL for the function that returns the array of strings for the COM component would look like,
[id(1)] HRESULT GetStringArray([out] SAFEARRAY(VARIANT)* StrArray);
The C++ implementation of the function should create a Safe Array of variants and initialize each variant with a BSTR as shown below:
STDMETHODIMP CNativeCOMComponent::GetStringArray(SAFEARRAY** pStrArray)
{
SAFEARRAYBOUND bounds[] = {{2, 0}}; //Array Contains 2 Elements starting from Index '0'
SAFEARRAY* pSA = SafeArrayCreate(VT_VARIANT,1,bounds); //Create a one-dimensional SafeArray of variants
long lIndex[1];
VARIANT var;
lIndex[0] = 0; // index of the element being inserted in the array
var.vt = VT_BSTR; // type of the element being inserted
var.bstrVal = ::SysAllocStringLen( L"The First String", 16 ); // the value of the element being inserted
HRESULT hr= SafeArrayPutElement(pSA, lIndex, &var); // insert the element
// repeat the insertion for one more element (at index 1)
lIndex[0] = 1;
var.vt = VT_BSTR;
var.bstrVal = ::SysAllocStringLen( L"The Second String", 17 );
hr = SafeArrayPutElement(pSA, lIndex, &var);
*pStrArray = pSA;
return S_OK;
}
In the above sample we are inserting two BSTR variants into the created Safe Array. Once the Array is filled with the variants (of type VT_BSTR), it can be retrieved from the C# managed code as shown below:
{
CNativeCOMComponent ComObj = new CNativeCOMComponent();
Array arr;
ComObj.GetStringArray(out arr); //arr would now hold the two strings we have sent from the COM code
}
Comments
Anonymous
December 16, 2009
Excellent!!! Thanks - I was trying to figure out this from last 1 day. You saved lot of my time. Thanks alot!!!!Anonymous
November 10, 2013
I have a c++ method as void getVariant(VARIANT vt); { if(vt!=NULL) { int len =sizeof(VARIANT); vt = (VARIANT)CoTaskMemAlloc(sizeof(VARIANT)); VariantInit(vt); vt->vt=VT_ARRAY|VT_R8|VT_BYREF;//VT_R8; SAFEARRAY psa=NULL; //double data[10]; // some sample data to write into the created safearray SAFEARRAYBOUND Bound; Bound.lLbound = 0; Bound.cElements = 10; psa = SafeArrayCreate(VT_R8, 1, &Bound); double HUGEP pdFreq; HRESULT hr = SafeArrayAccessData(psa, (void HUGEP FAR)&pdFreq); if (SUCCEEDED(hr)) { // copy sample values from data[] to this safearray for (DWORD i = 0; i < 10; i++) { *pdFreq++ =2.5; } } vt->parray=psa; } } in C# how to get this done and how to get the values on invoking this method. I have tried this but could not get result
- object obj = new object(); getVariant(ref obj); 2.object obj; getVariant(out obj);
- Anonymous
May 20, 2014
Thanks a ton. This could is still usable today, and is flawless. Thanks a lot again. I was really stuck with this issue from morning.