如何在 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
,也值得在<atlsafe.h>
中解构其源代码,让您更好地了解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#的主要内容,如果未能解决你的问题,请参考以下文章