12

我的 C# 方法需要从 C++ 调用

最初我的 C# 方法采用 double[] 类型的参数,但是当从 C++ 调用时,它变成了 SAFEARRAY

在 C++ 中,我需要从双精度数组中获取数据,并填充 SAFEARRAY。我还没有找到任何示例代码来执行此操作。

任何帮助表示赞赏

4

3 回答 3

27

以下是在 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++,那么最好使用在“atlsafe.h”中声明的 CComSafeArray。这是 SAFEARRAY 的包装。链接文本

于 2010-09-17T12:50:55.337 回答
8

继续@Liton 的回答,我想强调他的最后一句话,即 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函数的内容、时间、原因和方式。

于 2013-03-23T11:09:47.517 回答
2

不建议通过 SAFEARRAY。建议将 SAFEARRAY 放入 VARIANT 中。此外,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;
于 2014-07-09T14:01:19.900 回答