tags:

views:

210

answers:

2

Hi,

I need to return an array of structure (classes) from a C# library to an unmanaged C++ client. This is the function in the C# library:

[ComVisible(true)]
[Serializable]
public sealed class RetrieverProxy : IRetrieverProxy
{
    public IMyRecord[] RetrieveMyRecords(long[] ids)
    {
        IList<IMyRecord> result = new List<IMyRecord>();
        for (int i = 0; i < ids.Count(); i++)
        {
            result.Add(new MyRecord()
            {
              // some test data
            });
        }

        return result.ToArray();
    }
 }

MyRecord itself contains an array of structures, which are also COM visible and contain a double and a DateTime field.

I get the follow wrapper from regasm:

inline SAFEARRAY * IRetrieverProxy::RetrieveMyRecords (SAFEARRAY * ids) {
    SAFEARRAY * _result = 0;
    HRESULT _hr = raw_RetrieveMyRecords(ids, &_result);
    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _result;
}

From the client code, I invoke the library like the following:

SAFEARRAY *pMyRecordsSA;
SAFEARRAY *pIds;
// omitting pIds initialization, because from the library I can see 
// that they are ok
pMyRecordsSA = pIRetrieverProxy->RetrieveMyRecords(pIds);

The problem I have is how to retrieve the results which are now stored in pMyRecordsSA. I have tried the following but I it's not working:

    IMyRecordPtr pIMyRecords(__uuidof(MyRecord));
    HRESULT hr = SafeArrayAccessData(pMyRecordsSA, (void**)&pIMyRecords);

but then trying to use the pIMyRecords pointer gives an access violation (hr is 0K).

Any ideas? I am really stuck on this.

A: 

Take a look at CComSafeArray it might save you some time.

Paul Arnold
+1  A: 

It turned out that I just needed "another level of indirection". That is, a pointer to pointer vs a simple pointer.

IMyRecords** pIMyRecords; 
HRESULT hr = SafeArrayAccessData(pMyRecordsSA, (void**)&pIMyRecords);

This did the trick.

Stefano Ricciardi