无法将ByRef VARIANT数组转换为SAFEARRAY

Cannot convert ByRef VARIANT array to SAFEARRAY

本文关键字:转换 SAFEARRAY 数组 VARIANT ByRef      更新时间:2023-10-16

我正在编写一个C++DLL,以便从Excel VBA访问(它只是完成数学方程,不需要从工作表访问)。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数组作为VARIANT数据类型传递给我的C++函数ByValByRef,并且它似乎被正确接收。当我尝试在使用SafeArrayAccessData将数组转换为SAFEARRAY之后读取数组的内容时,就会出现问题。SAFEARRAY转换似乎有效,但数组的内容不正确。以下是我的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,则会出现错误。CCD_ 11返回的值与CCD_。

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

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函数(Iehttp://support.microsoft.com/kb/167668这略有不同,但在我关注的点上是相同的)。

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

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

pSafeArrayInput0 = *V_ARRAYREF(input0);