DLL
概要編集
かつてコンピューターのリソースが乏しかった時代、複数のプログラムでひとつのライブラリを共有しようという夢のような概念が生まれた。 誰もが絶賛した。
だが、その先にあったのはDLL地獄であった。
人々は奪い合い、殺し合い、混沌だけが残った。
DLLの使い方編集
test.dllのint test(int a)という関数を利用することを考える。
静的リンクの利点はプログラムが簡単になることだが、欠点はDLLがないと起動できなくなることなので、 拡張機能を提供するには向かない。
逆に、動的リンクの利点はDLLがなくてもプログラム内でエラー処理をすればいいことだが、 プログラムが若干複雑になるという欠点がある。
C言語編集
静的リンク編集
1.インポートライブラリを作成する
>pexports test.dll > test.def >dlltool --dllname test.dll --input-def test.def --output-lib libtest.a
2.プログラムをコンパイルする
/* usetest.c */
#include <stdio.h>
/* DLLに付属のC言語用ヘッダがあれば、それを使うべきである */
__declspec (dllimport) int test(int a);
int main(void) {
int a;
scanf("%d",&a);
printf("%d\n",test(a));
return 0;
}
>gcc -o usetest.exe usetest.c -L. -ltest
動的リンク編集
/* usetest_d.c */
#include <stdio.h>
#include <windows.h>
/* 関数ポインタの宣言 */
typedef int (*test_p)(int a);
int main(void) {
test_p test;
HMODULE hDll;
int a;
/* DLL自体の読み込み */
hDll=LoadLibrary("test.dll");
if(hDll==NULL) {
puts("DLL load error!");
return 1;
}
/* DLL内の関数の読み込み */
test=(test_p)GetProcAddress(hDll,"test");
if(test==NULL) {
puts("function test load error!");
FreeLibrary(hDll);
return 1;
}
scanf("%d",&a);
printf("%d\n",test(a));
/* DLLの開放 */
FreeLibrary(hDll);
return 0;
}
>gcc -o usetest_d.exe usetest_d.c
HSP3編集
;使用するDLLの名前を設定する #uselib "test.dll" ;命令として登録する #func test_o "test" int ;関数として登録する #cfunc test_f "test" int in=0 input in,100,30,100 button goto "命令を実行",*useorder button goto "関数を実行",*usefunc stop *useorder test_o in dialog "stat="+str(stat),0,"命令" stop *usefunc dialog str(test_f(in)),0,"関数" stop
Excel編集
'使用するDLLと関数の宣言 '変数を値渡しする際は、ByValをつけないといけない Private Declare Function test Lib "test.dll" (ByVal a As Long) As Long Sub Auto_Open() Dim rawInput As String Dim inputValue As Long 'xlsファイルのあるディレクトリにあるDLLを使うのに必要 ChDrive ThisWorkbook.Path ChDir ThisWorkbook.Path rawInput = InputBox("aを入力", "DLLサンプル", "0") If rawInput <> "" Then inputValue = Val(rawInput) MsgBox Str(test(inputValue)), vbOKOnly, "戻り値" End If End Sub
理論上はこれでできるはずだが、一部のDLLは読み込めないようである(後述)。
Active Basic 5編集
#console Declare Function test Lib "test.dll" (a As Long) As Long Dim a As Long Dim result As Long Input a result=test(a) Print result
なでしこ編集
●test(a)=DLL("test.dll","int test(int a)") 「aを入力してください。」で数値入力。 引数はそれを整数変換。 test(引数)をいう。
DLLの作り方編集
.NET Framework =編集
Visual C#を使用しても拡張子が.dllのファイルは作れるようだが、ここで扱うDLLとは別物である。
.NET Frameworkにおける.dllファイルはエントリポイントを持たない共通中間言語のバイナリ表現であり、従来のDLLとはまったくの別物である。紛らわしいことに拡張子が一緒だがまったくの別物である。
ここだけの話、.NET Frameworkの.exeファイルは.dllファイルのように扱える。
C言語編集
/* test_dll.h */
#ifndef TEST_DLL_H_GUARD
#define TEST_DLL_H_GUARD
/* WINAPIマクロを使用するのに必要 */
#include <windows.h>
/* おまじない */
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else
# define DLLIMPORT __declspec (dllimport)
#endif
/* ここにエクスポートしたい関数のプロトタイプ宣言をDLLIMPORTを付けて書く */
/* DLLIMPORTと戻り値の型の間にWINAPIと書かないと、Excel2007では読み込めないようである。 */
/* C言語(静的/動的リンク、gcc4.7.2)およびHSP3.2ではWINAPIがあってもなくても読み込めるようである。 */
DLLIMPORT WINAPI int test(int a);
#endif
/* test_dll.c */
#include "dll.h"
/* おまじない */
BOOL APIENTRY DllMain (HINSTANCE hInst,DWORD reason,LPVOID reserved) {
return TRUE;
}
/* このあたりに関数の本体を書く */
DLLIMPORT WINAPI int test(int a) {
return a*a+a+1;
}
>gcc -static -c test_dll.c -o test_dll.o -DBUILDING_DLL=1 >dllwrap --output-def libtest.def --implib libtest.a test_dll.o --no-export-all-symbols --add-stdcall-alias -o test.dll
この方法ならインポートライブラリも同時に作成してくれるので、使用時に作り直す必要はない。
Active Basic 5編集
- 新規作成を押す
- 「プロジェクト」を選んでOKを押す
- プロジェクト名を入力し、「DLL - プロシージャ ライブラリ」を選択して次へを押す
- 次へを押す
- 完了を押す
- 表示されたコードのDllMain関数の定義の下に下記のソースコードを書く
- リリース コンパイルを押す
'エクスポートしたい関数のFunction/Subと名前の間にExportと書く Function Export test(a As Long) As Long test=a*a+a+1 End Function
これで作成したDLLもExcel2007で読み込めるようである。