3

I have the following in my IDL which MIDL seems to like just fine. I am trying to create a method that returns an array of byte arrays (not a matrix). I am having a problem on the C++ side where neither of the ATL::CComSafeArray<LPSAFEARRAY> or ATL::CComSafeArray<ATL::CComSafeArray<byte> > is liked by the compiler. I get a error C2039: 'type' : is not a member of 'ATL::_ATL_AutomationType<T>'.

[id(1001)] HRESULT Find([out] SAFEARRAY(SAFEARRAY(byte))* features);

STDMETHOD(Find)(/*[out]*/ SAFEARRAY** features)

Is there a better way of passing array of byte arrays around (I am crossing process boundaries)?

wpfwannabe
  • 14,587
  • 16
  • 78
  • 129

1 Answers1

3

Ok, try this (C++ ATL EXE server):

[
    object,
    uuid(F7F8E65F-EBAD-4191-B916-2DB2A1EA0720),
    dual,
    nonextensible,
    helpstring("IAofA Interface"),
    pointer_default(unique)
]
interface IAofA : IDispatch{
    [id(1), helpstring("method GetArray")] HRESULT GetArray([out,retval] VARIANT* pVals);
};

CComVariant CreateByteArrayAsVariant(BYTE *pData, ULONG size)
{
    CComSafeArray<BYTE> sa(size);
    for (ULONG i=0; i!=size; ++i)
    {
        sa.SetAt(i, pData[i]);
    }

    CComVariant var(sa);

    return var;
}


STDMETHODIMP CAofA::GetArray(VARIANT* pVals)
{
    CComSafeArray<VARIANT> sa(3);

    BYTE a[] = {1};
    BYTE b[] = {1, 2};
    BYTE c[] = {3, 2, 1};

    sa.SetAt(0, CreateByteArrayAsVariant(a, sizeof(a)));
    sa.SetAt(1, CreateByteArrayAsVariant(b, sizeof(b)));
    sa.SetAt(2, CreateByteArrayAsVariant(c, sizeof(c)));

    CComVariant var(sa);

    var.Detach(pVals);

    return S_OK;
}

Here's a VB.net client:

Imports AofAServerLib

Module Module1

    Sub Main()
        Dim s As IAofA = New AofA
        Dim a() = s.GetArray

        For i As Integer = 0 To a.Length - 1
            For j As Integer = 0 To a(i).Length - 1
                Console.Write(a(i)(j))
                Console.Write(" ")
            Next
            Console.WriteLine()
        Next
    End Sub

End Module

No error checking, but it works.

Steve
  • 1,760
  • 10
  • 18
  • This is the way to go. You cannot create a safearray of safearray elements (see the restrictions of the `SafeArrayCreate()` function), but you can create a safearray of variant elements each containing a safearray. – Remy Lebeau Aug 07 '12 at 05:30
  • I wonder if there is something specific about VB.NET and VARIANTs but I can't seem to make this work with a C# client. – wpfwannabe Aug 08 '12 at 11:55
  • OK, I made it work. I had some problems with VT type. For anybody interested the IDL method can be `[out] SAFEARRAY(VARIANT)*` instead of `[out] VARIANT*`. – wpfwannabe Aug 08 '12 at 12:24