VBAから使えるDLLの作成(VC++)

やりたいこと

VC++でDLLを作成し、ExcelVBAから呼び出す。
ただし、DLLはシステムに登録せず、Excellファイルと同じフォルダに置く。

DLLのプロジェクト作成

プロジェクトの新規作成で、言語に「C++」を選択し、「ダイナミック リンク ライブラリ(DLL)」を選択して、適当な名前のプロジェクトを作成する。ここではプロジェクト名を hoge とする。

DLLで公開する関数の定義

下記の要領で定義する。

extern "C" __declspec(dllexport) int __stdcall piyo(int foo)
{
    return foo * foo;
}
  • extern "C" は、C++形式でなくC言語形式のリンケージを指定
  • __declspec(dllexport) は、DLLで公開することを指定
  • __stdcall は、呼び出し規約(引数の渡し方)を指定

下記のようなマクロを定義しておくと簡潔になる。

#define DLLEXPORT    extern "C" __declspec(dllexport)

DEFファイルの記述

VC++アプリからDLLを使うなら上記の関数定義だけでよいが、VBAからVC++のDLLを使う場合は、DEFファイルを定義して公開関数名を宣言しておく。そうでないと _piyo@4 のような修飾がついた関数名になってしまう。

「プロジェクト」>「新しい項目の追加」で「Visual C++」>「コード」>「モジュール定義ファイル」を選択して、適当な名前のDEFファイルを作成し、下記の要領で記述する。

LIBRARY    "hoge"

EXPORTS
    piyo

【参考記事】

DLLをビルドする

Excelが32bit版か64bit版かに合わせてx86またはx64でビルドすること。

VBAでDLLの関数を宣言する

Excelが32bit版か64bit版かで異なるDLLの関数を宣言するには下記のようにする。

#If Win64 Then
Declare PtrSafe Function piyo Lib "hoge_64.dll" (ByVal foo As Long) As Long
#Else
Declare PtrSafe Function piyo Lib "hoge_32.dll" (ByVal foo As Long) As Long
#End If

【参考記事】

VBAの実行時にDLLをロードする

DLLはパスの通っているディレクトリにないと読み込めない。
今回のようにパスの通ってないディレクトリにDLLを置く場合には下記のようにしてDLLをロードする。
Excelが32bit版か64bit版かの区別にも注意。

Declare PtrSafe Function LoadLibrary Lib "kernel32.dll" _
            Alias "LoadLibraryA" (ByVal fileName As String) As Long

Declare PtrSafe Function FreeLibrary Lib "kernel32.dll" _
        (ByVal hLibModule As Long) As Long

#If Win64 Then
Const HOGE_DLL_FILENAME = "\hoge_64.dll"
#Else
Const HOGE_DLL_FILENAME = "\hoge_32.dll"
#End If
Dim lib_handle As Long

    ' DLLのロード
    lib_handle = LoadLibrary(ThisWorkbook.Path + HOGE_DLL_FILENAME )
    
    ' DLLのアンロード
    FreeLibrary (lib_handle)

VBAでDLLの関数を呼び出す

    Dim x As Integer
    Dim y As Integer
    x = Range("A1").Value
    y = piyo(x)
    Range("A2").Value = y