空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

ExcelのVBAで使えるDLLを、C++(Visual Studio 2017)で作る。・・・その4.3(非配列Variant型変数による配列受け渡し編)

初めに

前回の予告通り、今回は非配列のVariant型変数に配列を格納して、DLLとの受け渡しをしてみます。

処理

処理方法は、これまでにやってきた事の組み合わせで出来ます。

DLL側でVariant型を受け取る処理は、文字列の受け渡しを行った時と同じ。
受け取ってから、VARIANT型変数のvtを見て、配列かどうかの判断を行います。
配列であることの確認できれば、VARIANT型変数のparrayに目的のSAFEARRAYがあります。
SAFEARRAYがわかれば、あとは、前回の処理を使えます。

コード

DLL

AccessibleFromVBA.h
追加分

    ACCESSIBLEFROMVBA_API void WINAPI GetArrayV(LPVARIANT pv);
    ACCESSIBLEFROMVBA_API void WINAPI SetArrayV(const LPVARIANT pv);

AccessibleFromVBA.cpp

AccessibleFromVBA.def

LIBRARY AccessibleFromVba

EXPORTS
    DoNothing
    GetNumberI
    GetNumberI2
    SetString
    SetStringS
    GetStringByParam
    GetStringByParamS
    GetStringByRetVal
    GetStringByRetValS
    GetArrayPE
    GetArrayAD
    GetArray2
    SetArrayGE
    SetArrayAD
    GetArrayV
    SetArrayV
VBA
Private Declare Sub SetArrayV Lib "C:\Datas\MyDatas\Developer\VisualStudioComunity2017\DllForVBA\ForTest\AccessibleFromVBA.dll" (ByRef v As Variant)
Private Declare Sub GetArrayV Lib "C:\Datas\MyDatas\Developer\VisualStudioComunity2017\DllForVBA\ForTest\AccessibleFromVBA.dll" (ByRef v As Variant)

Public Sub DllTestSetArrayV()

    Dim v   As Variant
    Dim lArray(3, 1)  As Long
    Dim sArray()    As String
    Dim dArray(2)   As Double
    Dim i   As Long
    Dim j   As Long

    ReDim sArray(2)

    sArray(0) = "Z1000"
    sArray(1) = "ZX-10R"
    sArray(2) = "Kawasaki"

    v = sArray

    Call SetArrayV(v)

    ReDim sArray(2, 2)

    v = sArray

    Call SetArrayV(v)

    For i = LBound(lArray, 1) To UBound(lArray, 1)
        For j = LBound(lArray, 2) To UBound(lArray, 2)
            lArray(i, j) = (i + 1) * 10 + j
        Next j
    Next i

'Arrayを使った場合、DLL側では、vt が VT_VARIANT | VT_ARRAY になるので注意が必要
'以下のコメントしたコードでは、VT_I4 | VT_ARRAY にはならない。
'    v = Array(1&, 2&, 3&, 4&)
    v = lArray

    Call SetArrayV(v)

    v = dArray

    Call SetArrayV(v)

End Sub

Public Sub DllTestGetArrayV()

    Dim vL  As Variant
    Dim vS  As Variant
    Dim i   As Long

    ReDim vL(3) As Long

    vL(0) = 100
    vL(1) = 200
    vL(2) = 300
    vL(3) = 400

    Debug.Print "Before"

    For i = LBound(vL) To UBound(vL)
        Debug.Print i, vL(i)
    Next i

    Call GetArrayV(vL)

    Debug.Print vbCrLf & "After"

    For i = LBound(vL) To UBound(vL)
        Debug.Print i, vL(i)
    Next i

    Debug.Print ""

    ReDim vS(2) As String

    vS(0) = "Z1000"
    vS(1) = "ZX-10R"
    vS(2) = "Ninja 900R"

    Debug.Print "Before"

    For i = LBound(vS) To UBound(vS)
        Debug.Print i, vS(i)
    Next i

    Call GetArrayV(vS)

    Debug.Print vbCrLf & "After"

    For i = LBound(vS) To UBound(vS)
        Debug.Print i, vS(i)
    Next i

End Sub

実行結果

DllTestSetArrayV

f:id:Z1000S:20191229211734j:plain
f:id:Z1000S:20191229211759j:plain
f:id:Z1000S:20191229211822j:plain
f:id:Z1000S:20191229211837j:plain

DllTestGetArrayV
Before
 0             100 
 1             200 
 2             300 
 3             400 

After
 0             200 
 1             400 
 2             600 
 3             800 

Before
 0            Z1000
 1            ZX-10R
 2            Ninja 900R

After
 0            Z1000 GetArrayV 0
 1            ZX-10R GetArrayV 1
 2            Ninja 900R GetArrayV 2

まとめ

今回は、過去の応用のようなものなので、サクッと簡単に終わらせてしまいました。

今後の予定は、

をまとめられればいいなと思っています。