1

Excel VBA からアクセスする C++ DLL を作成しています (数式を完了するだけで、ワークシートからアクセスする必要はありません)。DLL は現在の VBA コードを置き換えることを目的としており、パフォーマンスのために C/C++ で記述したいと考えています。

私は既存のコードを使用しており、現在の VBA 関数を新しい DLL に置き換えたいだけなので、単一のベクトル配列を含む 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に変換した後に配列の内容を読み取ろうとすると、問題が発生しSafeArrayAccessDataます。変換は機能しているように見えます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.pparraypSafeArrayInput0 = input0.pparrayd_m1.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;
}

私が見つけたすべての例は、ポインターによる入力の受け渡しが私の ReadArrayByRef 関数ごとに機能することを示しVARIANTます)。

ByRef 関数で何が間違っていますか?

4

1 に答える 1

2

フラグを確認する必要があります。VT_BYREFフラグが設定されている場合は、ポインターを逆参照して、次のように配列にアクセスします。

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