Я придумала решение, которое подходит для моих целей, несмотря на то, что оно не совсем то, что я изложил в этом вопросе.
Мое решение состояло в том, чтобы создать функцию COM, которая принимает SAFEARRAY в качестве параметра и изменяет его, а не возвращает созданный массив. Клиент VB6 создает массив и передает его в C ++ для заполнения. Я предполагаю, что в будущем будет использоваться функция-предшественник, которую VB6 вызывает для определения необходимого размера массива. Для справки вот фрагменты кода:
Функция интерфейса:
[id(4), helpstring("method PopulateWithStruct")] HRESULT PopulateWithStruct([in,out]SAFEARRAY (IReturnStruct*)*ppArray, [out,retval] long*plResult);
Где IReturnStruct - это интерфейс, содержащий значения свойств, выступающие в качестве структуры:
interface IReturnStruct : IDispatch
{
[propget, id(1), helpstring("property num1")] HRESULT num1([out, retval] long *pVal);
[propget, id(2), helpstring("property str1")] HRESULT str1([out, retval] BSTR *pVal);
};
И реализуется ReturnStruct
[
uuid(843870D0-E3B3-4123-82B4-74DE514C33C9),
helpstring("ReturnStruct Class")
]
coclass ReturnStruct
{
[default] interface IReturnStruct;
};
PopulateWithStruct имеет следующее определение:
STDMETHODIMP CCTestInterface::PopulateWithStruct(SAFEARRAY **ppArray, long *plResult)
{
long lLowerBound = -1;
long lUpperBound = -1;
SafeArrayGetLBound(*ppArray, 1, &lLowerBound);
SafeArrayGetUBound(*ppArray, 1, &lUpperBound);
long lArraySize = lUpperBound - lLowerBound;
VARTYPE type;
SafeArrayGetVartype(*ppArray, &type);
if (lArraySize > 0)
{
for ( int i = lLowerBound; i < lUpperBound; ++i)
{
CComPtr<CReturnStruct> pRetStruct;
HRESULT hr = CoCreateInstance(__uuidof(ReturnStruct), NULL, CLSCTX_ALL, __uuidof(IUnknown), reinterpret_cast<void **>(&pRetStruct));
if (SUCCEEDED(hr))
{
pRetStruct->Initialise();
hr = SafeArrayPutElement(*ppArray, (long*)&i, pRetStruct);
if (FAILED(hr))
{
return hr;
}
pRetStruct.Release();
}
}
SafeArrayUnaccessData(*ppArray);
}
*plResult = 1;
return S_OK;
}
На стороне VB:
Dim obj As ATL_SERVICETESTLib.CTestInterface
Set obj = New CTestInterface
Dim Result As Long
Dim RetStructs(3) As ReturnStruct
Result = obj.PopulateWithStruct(RetStructs())
Есть какие-нибудь комментарии по этому подходу?