将SAFEARRAY变量从c ++ dll传递给vba

时间:2017-05-03 06:43:35

标签: c++ vba matrix dll safearray

我在DLL中有以下代码,它应该从用VBA编写的例程中获取一些输入,用它做一些事情,然后返回两个2D数组(这样一个函数)并不是真的可行,此外,如果我想返回一个包含其他两个的数组,我必须面对VBA中的代码优化问题),可以从VBA访问。 不用多说,代码看起来像这样:

void _stdcall MySub(VARIANT RealCo, VARIANT ImagCo, VARIANT RealCr, VARIANT ImagCr, ULONG PointsTheta, ULONG PointsPhi, double Res, VARIANT CoPol, VARIANT CrPol)
{

/* Do my stuff here, and at the end produces the following arrays */

CoPol.vt = VT_ARRAY | VT_VARIANT;
CrPol.vt = VT_ARRAY | VT_VARIANT;
sab2[1].lLbound = 0; sab2[1].cElements = 360;
sab2[0].lLbound = 0; sab2[0].cElements = 360;
CoPol.parray = SafeArrayCreate(VT_VARIANT, 2, sab2);
CrPol.parray = SafeArrayCreate(VT_VARIANT, 2, sab2);

/* Those arrays are then stuffed with data */

}

我从VBA打电话如下:

Private Declare Sub MySub Lib "Mypath/MyFile.dll" ( _
        ByVal RealCo As Variant, _
        ByVal ImagCo As Variant, _
        ByVal RealCr As Variant, _
        ByVal ImagCr As Variant, _
        ByVal PointsTheta As Long, _
        ByVal PointsPhi As Long, _
        ByVal Res As Double, _
        ByVal CoPol As Variant, _
        ByVal CrPol As Variant)

Dim CoPol As Variant, CrPol As Variant

' [...]

MySub CVar(RealCo), CVar(ImagCo), CVar(RealCr), CVar(ImagCr), PointsTheta, PointsPhi, Resolution, CoPol, CrPol

CVar是因为输入数组RealCoRealCrImagCoImagCr实际上是VBA中的Single类型。

它有效,但我的问题如下:当我从C ++中的最后一个}移动到VBA时,CoPolCrPol的内容(这是我的两个矩阵)想在VBA代码中进一步使用)消失。

请注意,我实际上可以调试代码并检查CoPolCrPol是否包含数据。我试图将它们传递给C ++中的另一个子程序,因为它也不起作用,我提出了通过引用传递它们的解决方案:

void _stdcall MySub(VARIANT RealCo, VARIANT ImagCo, VARIANT RealCr, VARIANT ImagCr, ULONG PointsTheta, ULONG PointsPhi, double Res, VARIANT &CoPol, VARIANT &CrPol)

这解决了我在C ++ 中的问题,但在C ++和VBA之间没有解决。我也尝试过返回指向VARIANTS的指针,并调用所需的数组ByRefAs Long,但它不起作用(CoPolCrPol然后VBA只是一个Long号码,我无法使用。)

为了使VBA能够访问C ++内置矩阵内的值,我应该写什么?

编辑:如果你想进行投票,至少解释原因。

1 个答案:

答案 0 :(得分:1)

如果用C ++中的单个函数调用分配内存,你如何释放内存?

我会以另一种方式做到这一点;在VBA中声明并调暗数组,然后将指向数组数据的指针传递给C ++函数,然后用函数填充它。

(顺便说一句,我认为它的__stdcall有两个下划线。)

void __stdcall fillarray(const int n, double *out) {
    for (int i = 0; i < n; ++i) {
        out[i] = i;
    }
}

然后

Public Declare PtrSafe Sub fillarray Lib "Mypath/MyFile.dll" (ByVal n As Long, ByRef out As Double)

Dim A() as Double
Redim A(1 to 100)
fillarray 100, A(1)   'A(1) first element pointing to data