単純な DLL の作成
ここでは簡単な DLL を作成します。以前はソースコードを複数のファイルに分割しましたが、 ここでは DLL を作ることによって、実行時のバイナリを複数に分割します。
EXE ファイルのエントリポイントが WinMain になるように、DLL の既定のエントリポイントは DllMain になります。 しかし DLL のロード時などのイベントで特にやりたいことが無ければ、書かなくても構いません。
DLL を作るときに、リンカオプションで /DLL を渡していること、 DEF ファイルにエクスポート関数の名前を記載することに注意してください。
DLL をビルドするときに、ライブラリファイル (*.lib) も生成されます。ライブラリファイルは、この DLL を利用する側の プログラムをビルドするときに使用します。
この資料では簡単な DLL を作って、動作を確認してみましょう。
DLL の作成
以下の内容を username.cpp として保存します。
#include <windows.h> #include <lmcons.h> #include <tchar.h> #include <stdio.h> BOOL __stdcall PrintUserName() { TCHAR szUserName[UNLEN + 1]; DWORD dwUNLen = UNLEN; if( !GetUserName( (LPTSTR) szUserName, &dwUNLen ) ) { printf("Error: %u", GetLastError() ); return FALSE; } _tprintf( TEXT("%s\n"), szUserName ); return TRUE; }
以下の内容を username.h として保存します。
#pragma once #include <windows.h> BOOL __stdcall PrintUserName();
以下の内容を makefile として保存します。
TARGETNAME=username DEFFILE=username OUTDIR=.\chk ALL : "$(OUTDIR)\$(TARGETNAME).dll" "$(OUTDIR)" : @if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" CPP_PROJ=\ /MT\ /W4\ /Fo"$(OUTDIR)\\"\ /Fd"$(OUTDIR)\\"\ /c LINK32=link.exe LINK32_FLAGS=\ advapi32.lib\ /subsystem:windows\ /pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\ /debug\ /RELEASE\ /out:"$(OUTDIR)\$(TARGETNAME).dll"\ /DLL\ /DEF:$(DEFFILE).def LINK32_OBJS= \ "$(OUTDIR)\$(TARGETNAME).obj" "$(OUTDIR)\$(TARGETNAME).dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS) .cpp{$(OUTDIR)}.obj: $(CPP) $(CPP_PROJ) $<
username.def として以下を保存します。
LIBRARY username EXPORTS PrintUserName
上記を全部同じディレクトリに保存して、nmake すると chk というサブディレクトリの中に DLL や LIB ファイルが作成されるはずです。
> nmake -a
Microsoft (R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
cl /MT /W4 /Fo".\chk\\" /Fd".\chk\\" /c "username.cpp"
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
username.cpp
link.exe advapi32.lib /subsystem:windows /pdb:".\chk\username.pdb"
/debug /RELEASE /out:".\chk\username.dll" /DLL /DEF:username.def ".\chk\us
ername.obj"
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library .\chk\username.lib and object .\chk\username.exp
>
DLL を使うプログラムの作成
test.cpp として以下の内容を保存します。
#include <windows.h> #include <tchar.h> #include "username.h" int main(int argc, LPTSTR argv[]) { PrintUserName(); return 0; }
makefile は以下です。
TARGETNAME=test
OUTDIR=.\chk
LINK32=link.exe
ALL : "$(OUTDIR)\$(TARGETNAME).exe"
CPPFLAGS=\
/nologo\
/MT\
/W4\
/Fo"$(OUTDIR)\\"\
/Fd"$(OUTDIR)\\"\
/c\
/Zi\
/DWIN32\
/DUNICODE\
/D_UNICODE\
/D_CRTBLD
LINK32_FLAGS=\
username.lib\
/nologo\
/subsystem:console\
/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
/machine:I386\
/out:"$(OUTDIR)\$(TARGETNAME).exe"\
/DEBUG
LINK32_OBJS= \
"$(OUTDIR)\$(TARGETNAME).obj"
"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
$(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)
"$(OUTDIR)" :
@if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
.cpp{$(OUTDIR)}.obj:
$(CPP) $(CPPFLAGS) $<
さらに test.cpp と同じディレクトリに、上の DLL 作成で用いた username.h と、DLL 作成時に同時に生成された username.lib をコピーします。
上記を nmake すると、chk サブディレクトリに test.exe が作成されます。
test.exe は実行するために username.dll を必要とします。上記で作成した username.dll を test.exe と同じディレクトリにコピーします。
これで test.exe を実行することができます。