2010-09-16 99 views
10

我的C#方法从C++如何创建和初始化在C++双打SAFEARRAY传递给C#

调用

本来我的C#方法接受类型的参数双重[],但是从C调用时++变成SAFEARRAY

在C++中,我需要从一个双精度数组中取数据,并填充一个SAFEARRAY。我还没有找到任何示例代码来做到这一点。

任何帮助表示赞赏

回答

23

以下是在C创建一个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为C++,然后更好地利用CComSafeArray在 “atlsafe.h” 声明的指针。这是SAFEARRAY的包装。 link text

+0

大码,不好说。 – Contango 2010-10-08 14:51:11

+0

这篇文章帮助了我很多。谢谢。但是使用这样的功能给我留下了一个空的saData-Pointer。 – Teetrinker 2011-11-30 15:49:51

+0

@Teetrinker - 调用SafeArrayDestroy后,saData将为空。我已经添加了一些评论给我的代码。 – Liton 2012-01-16 10:15:28

6

继续@利顿的回答,我想强调他的最后一句话,即ATL的CComSafeArray。这真的可以为你节省很多打字。 CComSafeArray有C++构造函数,析构函数,包含[]的运算符重载,它给你对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

不推荐传递SAFEARRAYs。建议将SAFEARRAY放入VARIANT中。此外,SAFEARRAY应该保存VARIANT数据。这给了所有世界上最好的东西,并使VARIANT的VARIANT SAFEARRAY更适用于其他语言。例如。 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;