Search code examples
c#c++comclrcom-interop

C# ArrayList with C++ Interop


Got this in C#

public static ArrayList MyFct() 
{
  var x = new ArrayList();
  x.Add(5);
  return x
}

On C++ side with Interop, after calling Invoke_3(), I get a variant_t which contains my array, but how can I "extract" it ?

(for instance I would like to get the number of items, etc.)


Solution

  • This is a VARIANT (variant_t is a wrapper that comes from comdef.h / #import statement) that contains an IDispatch reference, so you can use IDispatch's methods, for example like this (error checks omitted):

    variant_t v;
    HRESULT hr = unk->GetList(&v); // get my VARIANT that contains an ArrayList reference
    
    // get "Count" method dispid
    LPOLESTR countName = (LPOLESTR)L"Count";
    DISPID dispidCount;
    hr = V_DISPATCH(&v)->GetIDsOfNames(IID_NULL, &countName, DISPATCH_METHOD, 0, &dispidCount);
    
    DISPPARAMS dp = { nullptr, nullptr, 0, 0 };
    variant_t count;
    hr = V_DISPATCH(&v)->Invoke(dispidCount, IID_NULL, 0, DISPATCH_METHOD, &dp, &count, nullptr, nullptr);
    
    // get "Item(i)" method dispid
    LPOLESTR itemName = (LPOLESTR)L"Item";
    DISPID dispidName;
    hr = V_DISPATCH(&v)->GetIDsOfNames(IID_NULL, &itemName, DISPATCH_METHOD, 0, &dispidName);
    
    for (int i = 0; i < V_I4(&count); i++)
    {
        // build index as variant
        variant_t index(i);
        DISPPARAMS dpIndex = { &index, nullptr, 1, 0 };
    
        // get item(i)
        variant_t item;
        hr = V_DISPATCH(&v)->Invoke(dispidName, IID_NULL, 0, DISPATCH_METHOD, &dpIndex, &item, nullptr, nullptr);
    
        // item can be a scalar value
        // String => VT_BSTR, Int32 => VT_I4, etc.
        // or another ComVisible object => VT_DISPATCH, VT_UNKNOWN, etc.
    }