Как создать и инициализировать SAFEARRAY удвоений в С++ для перехода на С#

Мой С# метод должен быть вызван из С++

Первоначально мой метод С# принимает параметр типа double [], но при вызове из С++ он становится SAFEARRAY

В С++ мне нужно взять данные из массива двойников и заполнить SAFEARRAY. Я не нашел код примера для этого.

Любая помощь приветствуется

Ответ 1

Ниже приведен код для создания safearray в С++.

#include<oaidl.h>

void CreateSafeArray(SAFEARRAY** saData)        
{
    double data[10]; // some sample data to write into the created safearray
    SAFEARRAYBOUND  Bound;
    Bound.lLbound   = 0;
    Bound.cElements = 10;

    *saData = SafeArrayCreate(VT_R8, 1, &Bound);

    double HUGEP *pdFreq;
    HRESULT hr = SafeArrayAccessData(*saData, (void HUGEP* FAR*)&pdFreq);
    if (SUCCEEDED(hr))
    {
            // copy sample values from data[] to this safearray
        for (DWORD i = 0; i < 10; i++)
        {
            *pdFreq++ = data[i];
        }
        SafeArrayUnaccessData(*saData);
    }
}

Освободите указатель, когда вы закончите, как следующий код -

  SAFEARRAY* saData;
  CreateSafeArray(&saData); // Create the safe array
  // use the safearray
  ...
  ...

  // Call the SafeArrayDestroy to destroy the safearray 
  SafeArrayDestroy(saData);
  saData = NULL; // set the pointer to NULL

Если вы используете ATL для С++, тогда лучше использовать CComSafeArray, объявленный в "atlsafe.h". Это оболочка для SAFEARRAY. текст ссылки

Ответ 2

Продолжая отвечать на @Liton, я хочу подчеркнуть его последнее предложение, т.е. ATL CComSafeArray. Это действительно может сэкономить вам много набрав. CComSafeArray имеет конструкторы С++, деструкторы, перегрузки операторов, в том числе один для [], который дает ссылку на чтение/запись любому элементу в SAFEARRAY. Короче говоря, вы можете сосредоточиться на своей бизнес-логике и не беспокоиться о сантехнике SAFEARRAY:

#include <atlbase.h>
#include <atlsafe.h>
// ...

    CComSafeArray<double> arr(10);
    arr[0] = 2.0;
    arr[1] = 3.0;
    arr[2] = 5.0;
    // ...

По крайней мере, даже если вы не собираетесь использовать CComSafeArray, стоит деконструировать его исходный код в <atlsafe.h>, чтобы лучше понять функции what, when, why and how on SAFEARRAY.

Ответ 3

Передача SAFEARRAY не рекомендуется. Рекомендуется помещать SAFEARRAY в VARIANT. Кроме того, SAFEARRAY должен хранить данные VARIANT. Это дает лучшее из всех миров и делает переход VARIANT SAFEARRAY of VARIANT более полезным для других языков. Например. С++ для VB/С# (обратите внимание, что до вызывающего абонента освобождается/уничтожает SAFEARRAY)

Основываясь на предыдущем коде

// A VARIANT holding a SAFEARRAY of VARIANTs
VARIANT vRet;

SAFEARRAYBOUND Bound;
Bound.lLbound = 0;
Bound.cElements = 10;

SAFEARRAY * psaData = SafeArrayCreate(VT_VARIANT, 1, &Bound);

VARIANT HUGEP * pData = NULL;
HRESULT hr = SafeArrayAccessData(psaData, (void HUGEP * FAR *)&pData);
if (SUCCEEDED(hr))
{
    for (short i = 0; i < 10; ++i,++pData)
    {
        ::VariantInit(pData);
        pData->vt = VT_I2;
        pData->iVal = i;
    }

    SafeArrayUnaccessData(psaData);
}

vRet.vt = VT_ARRAY | VT_VARIANT;
vRet.parray = psaData;