2010-09-16 21 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;