1

我正在编写一个可以从 Excel VBA 访问的 C++ DLL(它只是完成数学方程式,不需要从工作表中访问)。该 DLL 旨在替换当前的 VBA 代码,我想用 C/C++ 编写它以提高性能。

由于我使用的是现有代码并且只是想用新的 DLL 替换当前的 VBA 函数,因此我必须使用包含单个向量数组的 VBA 变体。以下是 VBA 调用代码的简略示例:

Sub VBACaller()
    Dim InputR0(1 To 5) As Variant, vResult As Variant

    InputR0(1) = 26.8
    InputR0(2) = 27.8
    InputR0(3) = 28.8
    InputR0(4) = 29.8

    vResult = ReadArrayVBA(InputR0)
End Sub

我可以将此 Variant 数组传递给我的 C++ 函数,也可以ByVal作为ByRef数据VARIANT类型传递,并且它似乎被正确接收。SAFEARRAY当我将数组转换为using后尝试读取数组的内容时,会出现我的问题SafeArrayAccessDataSAFEARRAY转换似乎有效,但数组的内容不正确。以下是我的 C++ 代码:

VARIANT __stdcall ReadArrayByRef(VARIANT *input0)
{
//Variable to assign value from Array
double d_m = 0;

//Check if this is a variant type or not
if (V_VT(input0) & VT_ARRAY)
{
    SAFEARRAY* pSafeArrayInput0 = NULL;
    pSafeArrayInput0 = V_ARRAY(input0);

    double* pVals;

    HRESULT hr = SafeArrayAccessData(pSafeArrayInput0, (void **)&pVals); // direct access to SA memory
    if (SUCCEEDED(hr))
    {
        long lLBound = -1, lUBound = 1;  // get array bounds
        SafeArrayGetLBound(pSafeArrayInput0, 1, &lLBound);
        SafeArrayGetUBound(pSafeArrayInput0, 1, &lUBound);

        if (lLBound > -1 && lUBound > -1)
        {
            d_m =  pVals[1];
        }
        SafeArrayUnaccessData(pSafeArrayInput0);
    }
}

//Output
VARIANT v;
VariantInit(&v);
v.vt = VT_R8;
v.dblVal = d_m;

return v;
}    

我发现的示例似乎表明.parray应该保存数据,但是检查input0表明它在.pparray. 如果我尝试分配pSafeArrayInput0 = input0.pparray它会出错。返回的值d_m类似于1.05319234616515E-307.

如果我将输入更改为,ByVal那么我可以使用以下 C++ 代码正确访问数组的元素(唯一的区别是 input0 的地址正在由SAFEARRAY.

VARIANT __stdcall ReadArrayByVal(VARIANT input0)
{
//Variable to assign value from Array
double d_m = 0;

//Check if this is a variant type or not
if (V_VT(&input0) & VT_ARRAY)
{
    SAFEARRAY* pSafeArrayInput0 = NULL;
    pSafeArrayInput0 = V_ARRAY(&input0);

    double* pVals;

    HRESULT hr = SafeArrayAccessData(pSafeArrayInput0, (void **)&pVals); // direct access to SA memory
    if (SUCCEEDED(hr))
    {
        long lLBound = -1, lUBound = 1;  // get array bounds
        SafeArrayGetLBound(pSafeArrayInput0, 1, &lLBound);
        SafeArrayGetUBound(pSafeArrayInput0, 1, &lUBound);

        if (lLBound > -1 && lUBound > -1)
        {
            d_m =  pVals[1];
        }
        SafeArrayUnaccessData(pSafeArrayInput0);
    }
}

VARIANT v; 
VariantInit(&v);
v.vt = VT_R8;
v.dblVal = d_m;

return v;
}

我发现的所有示例都表明,通过VARIANT指针传递输入应该适用于我的 ReadArrayByRef 函数(即http://support.microsoft.com/kb/167668,它略有不同但在我之后的点相同)。

我在 ByRef 函数中做错了什么?

4

1 回答 1

2

您应该检查VT_BYREF标志,如果已设置,请取消引用指针以访问数组,如下所示:

pSafeArrayInput0 = *V_ARRAYREF(input0);
于 2013-07-26T23:01:49.707 回答