DLL関数を作成する(引数あり)|C++でDLLを自作してExcelVBAで呼び出す方法③
前回、”HelloWorld”というメッセージを表示する「HelloWorld」関数を作成しました。
この関数は引数も戻り値もない、いうなればDLL内で完結している関数でした。
しかし、VBAでDLLの関数を使うときはVBAから何らかの入力があることが一般的です。
そこで今回はVBAからDLLの関数に引数として値を渡す関数を作成していきます。
VBAとC++では変数の型の違いが発生するものもあり値のやり取りはすこしクセがあります。本ページで紹介していない型について『C、C++の型とデータータイプ』ページもあわせて参照下さい。
DLLファイルを作成(引数あり)
今回は引数としてVBAから渡されたLong型の2つの値の和をメッセージボックスで表示する「AddNumber」関数を作成していきます。本関数はこれまでと同じDLLファイルに関数を追加していきます。本関数はこれまでと同じく「VBA_DLL.dll」内に追加していきます。
VisualStudioを閉じてしまった場合は「VBA_DLL.sln」を開いて追記していって下さい。
ヘッダーファイル (VBA_DLL.h)
まずは「AddNumber」関数を宣言します。
これまでと違い今回は引数があるので括弧内に引数の設定をします。
引数は「(引数の型 引数名)」の順で入力し、複数設定する場合はカンマ[,]で区切ります。
今回の関数では「a」「b」という2つのLong型の引数を設定します。
また、戻り値はないので戻り値の型は「void」とし、下記のように宣言します。
extern “C” VBADLL_API void AddNumber(long a, long b);
ソースファイル (VBA_DLL.cpp)
ヘッダーファイルに新たな関数「AddNumber」の宣言をしたので、ソースファイル(.cpp)側では関数の処理内容を書いていきます。コードは下記の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include "VBA_DLL.h" #include "windows.h" //MessageBox関数が含まれている //void EmptyProcess() は表示の関係上省略 //void HelloWorld() は表示の関係上省略 void AddNumber(long a, long b) { //引数の和を計算 long ans = a + b; //Long型をLPCSTR型に変換 TCHAR msg[1024]; wsprintf(msg, TEXT("%d"), ans); //引数の和を表示 MessageBox(NULL, msg, TEXT("DLL"), MB_OK); return; } |
このコードによりVBAより入力された2つのLong型の引数の和をメッセージボックスで表示することができます。(メッセージボックスのキャプションは前回と同じく「DLL」となっています)
コードについてはC++の内容になるので深くは解説しませんが、コメント文にも書いてある通り、入力された値の和をLong型の「ans」という変数に格納し、メッセージボックスで表示できるように型変換をしているだけの簡単な処理です。
そんなことよりもここで重要なのは”C++でどんな処理をしているのか”ではなく、”VBAから入力された値をC++内で扱うことができる”という点です。
Long型はC++もVBAも共通なので迷わず使うことができると思いますが、その他の型は共通でないものもあります。値がうまく渡せない場合は下記ページでC++とVBAでどの型とどの型が対応しているのかを確認してみて下さい。
VBAで作成したDLLファイルを呼び出す
上記のコードでDLLファイルを出力したら、VBAで呼び出してみます。コードは下記の通りです。
1 2 3 4 5 6 7 8 9 |
'DLLファイルの関数定義 Private Declare PtrSafe Sub AddNumber _ Lib "C:\programming\cpp\VBA_DLL\x64\Release\VBA_DLL.dll" (ByVal a As Long, ByVal b As Long) Sub Test() Call AddNumber(10, 20) End Sub |
これまでの関数と違い関数に引数があるので、VBA側でも引数の設定をする必要があります。
DLL内で宣言した引数と対応するように下記のように書きます。
Private Declare PtrSafe Sub 関数名 Lib “DLLファイル” (ByVal 引数名 As 引数の型)
‘※ 引数が複数ある場合はカンマ[,]で区切ることが可能
引数ありの場合は、DLLファイル内で設定した引数と対応するかたちでByVal形式で宣言します。
(※ByRef形式にすることも可能ですが、特に理由が無ければ基本的にはByVal形式にします)
この型が対応していないとうまく値を受け渡すことが出来ないので注意して下さい。
今回の関数の引数はLong型ですがC++もVBAも共通の型なので、VBA側もLong型で宣言します。
上記コードを実行することで、下画像のようなメッセージを表示させることができます。
引数の値を変えることでしっかりとDLL内の関数に値が渡っていることが確認できます。
まとめ
今回はDLLの関数として引数のある関数を新たに追加しました。
内容をまとめると下記の通りです。
C++側:(引数の型 引数名, 引数の型 引数名…)
VBA側:(ByVal 引数名 As 引数の型, ByVal 引数名 As 引数の型…)
C++とVBAで型が対応していないと値を受け渡せない
C++もVBAも引数ありの関数を宣言すること自体は難しくありませんが、型を対応させるところの難易度はかなり高いです。C++にはあってVBAにはない型、逆の場合もしかりでどうしても完全に対応することはできません。そのためここはいろいろ試行錯誤して徐々に慣れていく必要があります。
ちなみに本ページでは紹介していませんが、文字列を引数として渡す場合はC++側を「char」、VBA側を「String」にすることで渡すことができます。詳しくは次回の「DLL関数を作成する(戻り値あり)」で解説していきます。
【次回】DLL関数を作成する(戻り値あり)
【前回】DLL関数を作成する(引数なし)
目次へ戻る