如何在 C++ 中创建和初始化双精度的 SAFEARRAY 以传递给 C#

Posted

技术标签:

【中文标题】如何在 C++ 中创建和初始化双精度的 SAFEARRAY 以传递给 C#【英文标题】:How to create and initialize SAFEARRAY of doubles in C++ to pass to C# 【发布时间】:2010-09-16 21:08:30 【问题描述】:

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

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

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

感谢任何帮助

【问题讨论】:

【参考方案1】:

以下是在 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 的包装。 link text

【讨论】:

这篇文章对我帮助很大。谢谢。但是使用这样的函数给我留下了一个空的 saData-Pointer。 @Teerinker - 调用 SafeArrayDestroy 后 saData 将为空。我在我的代码中添加了一些 cmets。 谢谢,正是我需要的。但是,当一切都是 32 位或 64 位时,HUGEP 和 FAR 宏现在只是噪音。【参考方案2】:

继续@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,也值得在&lt;atlsafe.h&gt; 中解构其源代码,让您更好地了解SAFEARRAY 函数的内容、时间、原因和方式。

【讨论】:

【参考方案3】:

不建议通过 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;

【讨论】:

以上是关于如何在 C++ 中创建和初始化双精度的 SAFEARRAY 以传递给 C#的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 或 C 中创建和编写索引 png 图像

在 Xcode 控制台项目中创建和使用 C++ 库

在java中创建和初始化对象

如何在 OpenGL ES 2 中创建和使用 VBO

如何在 MATLAB MEX 文件中创建双精度的 N-D 矩阵?

如何在 C++ 中将用户输入验证为双精度?