Правильное использование ATL CComSafeArray при вызове из VB6 через OLE-автоматизацию? - PullRequest
3 голосов
/ 30 сентября 2019

В настоящее время я отлаживаю некоторый устаревший код ATL / C ++, который вызывается из Visual Basic 6 для поиска возможных утечек памяти / ресурсов.

Вызываемая функция получает массив по ссылке:

STDMETHODIMP Process::Evaluate(
    IDispatch** pVBColl,
    SAFEARRAY** pResults,
    VARIANT_BOOL* pRetVal)

Соответствующий IDL:

interface IProcess: IDispatch{
    [id(1337)] HRESULT Evaluate(
        [in,out] IDispatch** pVBColl,
        [in,out] SAFEARRAY(FLOAT)* pResults,
        [out,retval] VARIANT_BOOL* pRetVal);
    );

Теперь я нашел три различных решения, как получить доступ и изменить массив результатов и вернуть значения:

Первое решение:

CComSafeArray<FLOAT>& arrResults = reinterpret_cast<CComSafeArray<FLOAT>&>(*pResults);
arrResults[1] = 3.14;

2-е решение:

CComSafeArray<FLOAT> arrResults = *pResults;
arrResults[1] = 3.14;
*pResults = arrResults.Detach();

3-е решение:

CComSafeArray<FLOAT> arrResults;
arrResults.Attach(*pResults);
arrResults[1] = 3.14;
*pResults = arrResults.Detach();

Сейчасбольшой вопрос: какой из них правильный?
какой из них не просочился?
Какой правильный путь к массиву Attach / Detach / AddRef / Release, переданному по ссылке из VB в ATL / C ++?

Внимание: объявляются массивы [in, out], которые нельзя изменить.

...