Как создать и инициализировать SAFEARRAY двойников в C ++ для перехода на C # - PullRequest
11 голосов
/ 17 сентября 2010

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

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

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

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

Ответы [ 3 ]

26 голосов
/ 17 сентября 2010

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

#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 для C ++, тогда лучше использовать CComSafeArray, объявленный в "atlsafe.h".Это обертка для SAFEARRAY. текст ссылки

7 голосов
/ 23 марта 2013

Продолжая ответ @ Литона, я хочу подчеркнуть его последнее предложение, то есть ATL CComSafeArray.Это действительно может сэкономить вам много печатать.CComSafeArray имеет конструкторы C ++, деструкторы, операторные перегрузки, включая одну для for [], которая дает вам ссылку для чтения / записи на любой элемент в 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>, чтобы лучше понять, что, когда, почему и как работает SAFEARRAY.

2 голосов
/ 09 июля 2014

Передача SAFEARRAY не рекомендуется.Рекомендуется поместить SAFEARRAY в ВАРИАНТ.Кроме того, SAFEARRAY должен содержать данные VARIANT.Это дает лучшее из всех миров и делает передачу VARIANT SAFEARRAY из VARIANT более полезной для других языков.Например, от C ++ до VB / C # (обратите внимание, что вызывающий может освободить / уничтожить 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;
...