VC++2005でDLL作成、呼び出し、VBAからDLL呼び出し

DLLの実装方法、アプリケーションからの呼出し方法、
ExcelVBAからの呼び出し方法を紹介する。

1章 VisualC++2005を用いてDLLを作成する方法
2章 DLLを呼び出すアプリケーションの作成方法
3章 ExcelのVBAからDLLを呼び出す方法

2012/12/15 本文を推敲しました。章構成を若干見やすくしました。

1章 VisualC++2005を用いてDLLを作成する方法


VC++2005を用いてDLLを作成する方法を紹介する。

本記事ではサンプルとして、以下の関数を持つDLLを作成する。

int SampleFunc(int a, int b);//a+bをreturnする関数

後述の2章、3章ではこのDLLを呼び出す方法を紹介する。
3章ではVBAから呼び出せるよう若干の改造も行う。

1.1章 DLL作成プロジェクト(ソリューション)の作成

ファイル->新規作成->プロジェクトより、新しいプロジェクトダイアログを呼び出し、
 プロジェクトの種類:Visual C++ Win32
 テンプレート   :Win32プロジェクト
 プロジェクト名  :SampleDLL
とする。

Win32アプリケーションウィザードのアプリケーションの設定で、
 アプリケーションの種類:DLL
 空のプロジェクトにチェックを入れる
とする。

上記でDLLを作成するための空のプロジェクトができあがる。
次に、このプロジェクトにヘッダファイルとソースファイルを追加し、
SampleFunc()関数を提供するDLLとなるよう実装を行う。

1.2章 ヘッダファイルの作成

SampleDLL.hというヘッダファイルを追加する。

ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->新しい項目を選択し、
 テンプレート:C++ファイル(.cpp)とし、
 ファイル名 :SampleDLL.h
としてヘッダファイルを追加する。

ヘッダファイルには、以下のように記述する。

__declspec(dllexport)int SampleFunc(int a, int b);

通常の関数プロトタイプ宣言に、__declspec(dllexport)を追加したのみである。

なお、このヘッダファイルはDLL内部でのみ使用する。
DLLを呼び出すアプリケーションの実装時には、
DLLの機能を外部に公開するヘッダファイルが必要となるため、これも作成する。

ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->新しい項目
を選択し、
 テンプレート:C++ファイル(.cpp)とし、
 ファイル名 :SampleDLLAPI.h
としてヘッダファイルを追加し、以下のように記述する。

__declspec(dllimport)int SampleFunc(int a, int b);

通常の関数プロトタイプ宣言に、__declspec(dllimport)を追加したのみである。
また、単にSampleDLL.hの「dllexport」を「dllimport」に変えただけでもある。
(SampleDLL.hとSampleDLLAPI.hを#ifdef文の利用により、同一ファイルとしたサンプルソースを見かける。)

1.3章 ソースファイルの作成

SampleDLL.cppというソースファイルにDLLの機能を記述する。

ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->新しい項目を選択し、
 テンプレート:C++ファイル(.cpp)とし、
 ファイル名 :SampleDLL.cpp
としてソースファイル追加する。

以下のように記述する。

#include <windows.h>;
#include "SampleDLL.h"
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID opvReserved)
{
	switch(fdwReason){
	case DLL_PROCESS_ATTACH:	/*	プロセスにロードされた			*/
	case DLL_PROCESS_DETACH:	/*	プロセスからアンロードされた	*/
	case DLL_THREAD_ATTACH:		/*	新規スレッドが作成された		*/
	case DLL_THREAD_DETACH:		/*	スレッドが終了した				*/
		break;
	}
	return true;
}
__declspec(dllexport)int SampleFunc(int a, int b) 
{ 
	return a+b; 
}

DllMainの処理については単にtrueを返すだけでよい。
SampleFuncも通常の関数の定義に__declspec(dllexport)を追加したのみである。

以上で、DLL作成プロジェクトに、ヘッダファイルとソースファイルを追加できた。
またDLLが公開する関数としてSampleFunc()関数を実装した。
次にビルドを行う。

1.4章 プロジェクトのビルド

以下のファイルが生成される。
 SampleDLL.lib
 SampleDLL.dll

libファイルはこのDLLを使用するアプリケーション(2章で作成)のビルド時に必要となる。
dllファイルはこのDLLを使用するアプリケーション(2章で作成)の実行時に必要となる。

VC++2005を用いてDLLファイルを作成する方法は以上となる。
2章ではこのDLLを使用するアプリケーションの実装方法を紹介する。

2章 DLLを呼び出すアプリケーションの作成方法


VC++2005を用いてDLLファイルを呼び出すアプリケーションの作成方法を紹介する。

2.1章 プロジェクトの作成

簡単のために、コンソールアプリケーションとする。

ファイル->新規作成->プロジェクトより、新しいプロジェクトダイアログを呼び出し、
 プロジェクトの種類:Visual C++ Win32
 テンプレート   :Win32コンソールアプリケーション
 プロジェクト名  :SampleDLLUse
として、
Win32コンソールアプリケーションウィザードのアプリケーションの設定で、
 アプリケーションの種類:コンソールアプリケーション
 空のプロジェクト     :チェックを入れる
 プリコンパイル済みヘッダー:チェックを入れない
とする。

DLLを使用するアプリケーションのビルド(及びリンク)には以下が必要となる。
 DLLの公開ヘッダファイル(SampleDLLAPI.h)
 libファイル(SampleDLL.lib)

DLLを使用するアプリケーションの実行には以下が必要となる。
 dllファイル(SampleDLL.dll)

2.2章 ヘッダファイルの追加

1章で作成したDLLの外部公開ヘッダファイル(SampleDLLAPI.h)を追加する。
(SampleDLL.hはDLL内部用なので不要)

ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->既存の項目
を選択し、1章で作成したSampleDLLAPI.hを選択する。
(SampleDLLAPI.hをSampleDLLUseプロジェクト配下にコピーしておき、
それを選択するとよいだろう)

2.3章 libファイルの指定

libファイルはDLLを使用するアプリケーションのビルド(リンク)時に必要となる。

2.3.1章 リンカの設定
ソリューションエクスプローラのプロジェクト名のアイコン上で
右クリック->プロパティ->構成プロパティ->リンカ->入力->追加の依存ファイルに
SampleDLL.lib
と入力する。

2.3.2章 libファイルの格納
SampleDLLUseプロジェクトのフォルダに
SampleDLL.libを格納しておけば勝手に探してくれるので特に指定する必要はない。

SampleDLLUseプロジェクトのフォルダ以外の場所にある場合は、
ソリューションエクスプローラのプロジェクト名のアイコン上で
右クリック->プロパティ->構成プロパティ->リンカ->全般->追加のライブラリディレクトリに
SampleDLL.libが格納されているフォルダを指定する。
(この設定はDebug/Releaseビルド両方それぞれ実施する必要がある。)

2.4章 DLLファイルの格納

DLLファイルはDLLを使用するアプリケーションの実行時に必要となる。
これから作成するアプリケーション(SampleDLLUse.exe)と同じフォルダにSampleDLL.dllを格納しておけば
アプリケーション実行時に勝手に探して使ってくれるので特に指定する必要はない。

なお、DLLファイルは以下サイトで紹介されている検索パスのどこかに格納しておけばよい。
参考) Windows が使用する DLL 検索パス
 http://msdn.microsoft.com/ja-jp/library/7d83bc18%28v=vs.80%29.aspx

次にDLLを呼び出す機能を実装する。

2.5章 アプリケーションのソースファイル

ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->新しい項目を選択し、
 テンプレート:C++ファイル(.cpp)とし、
 ファイル名 :SampleDLLUse.cpp
としてソースファイル追加し、以下のように記述する

#include <stdio.h>;
#include "SampleDLLAPI.h"//ここでDLLの公開機能ヘッダをincludeしているので
int main(void)
{
	int a=10, b=3, c=0;
	c = SampleFunc(a, b);//ここでDLLの関数が呼べる
	printf("c = %dn", c);
	return 0;
}

SampleFunc関数は通常の関数の呼び出しと同じように記述できる。
SampleFunc関数がどのDLLに格納されているかの情報(リンカ向け情報)はSampleFunc.libに格納されている。
SampleFunc関数の実体はSampleFunc.dllに格納されている。

2.6章 プロジェクトのビルド、実行

cに13が格納されていることが確認できればDLLを呼び出すことができている。
以上がVC++2005を用いてDLLファイルを呼び出すアプリケーションの作成方法である。
3章ではExcelのVBAからDLLファイルを呼び出す方法を紹介する。

3章 ExcelのVBAからDLLを呼び出す方法


ExcelのVBAからDLLを呼び出す方法を紹介する。

3.1章 VBA向けDLLの作成

1章で作成したDLLをVBAから呼び出せるよう、若干の改造を行う。

3.1.1章 ヘッダファイルの改造
SampleDLL.hを改造する。
改造前

__declspec(dllexport)int SampleFunc(int a, int b);

改造後

__declspec(dllexport)int WINAPI SampleFunc(int a, int b);

WINAPIを付加するだけである。
WINAPIは引数をスタックにつむ順序がPASCAL型であることを示しており、
VBAからの関数呼び出し方がそのようになっているためだと思われる。

3.1.2章 ソースファイルの改造
SampleDLL.cppを改造する。
改造前

__declspec(dllexport)int SampleFunc(int a, int b)
{
	/*	1章と同じ	*/
}

改造後

__declspec(dllexport)int WINAPI SampleFunc(int a, int b)
{
	/*	1章と同じ	*/
}

こちらもWINAPIを付加するだけである。

3.1.3章 モジュール定義ファイルの追加
ソリューションエクスプローラのソースファイルアイコン上で
右クリック->追加->新しい項目を選択し、
 テンプレート:モジュール定義ファイル(.def)とし、
 ファイル名 :SampleDLL.def
としてソースファイル追加し、以下のように記述する

LIBRARY	"SampleDLL"
EXPORTS
  SampleFunc

上記改造の後、ビルドを行い、作成したDLLをExcelファイルと同じディレクトリに格納する。
2.4章で述べた検索パスであれば他のディレクトリでもよいと思われるが未確認。

3.2章 DLLの機能を呼び出すVBAの記述

3.2.1章 VBエディタの起動
Excelを起動し、Alt + F11でVisual Basic Editorを呼び出す。
以下が表示されていない場合は表示させる。
・表示->プロジェクトエクスプローラ
・表示->プロパティウィンドウ
・表示->コード
・表示->ウォッチウィンドウ

3.3.2章 標準モジュールの追加
プロジェクトエクスプローラの標準モジュール上で
右クリック->挿入->標準モジュール
として追加する。

(多分Module1というモジュールが追加されるが、このままでは分かりにくいので、
Module1を追加した状態で、プロパティウィンドウの
オブジェクト名を分かりやすい名前(DLLTest等)に書き直すとよい。)

3.3.3章 VBAソースコード
追加したモジュール名をダブルクリックでコードエディタ画面を出し、
以下のように記述する。

Declare Function TestFunc Lib "SampleDLL.dll" Alias "SampleFunc" (ByVal tmp1 As Long, ByVal tmp2 As Long) As Long
Sub DllTest()
    Dim a As Long
    Dim b As Long
    Dim c As Long
    a = 10
    b = 3
    c = TestFunc(a, b)
End Sub

3.3章 DLL呼び出し確認

F5キー押下によりVBAマクロを実行し、変数cが13になることが確認できればDLLを呼び出せている。
(End Subの行にブレークポイントを貼った状態でマクロを実行し、
変数cをウォッチウィンドウにドラッグすることで値を確認できる。)

以上の方法でExcelのVBAからDLLを呼び出すことができる。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です