単純な 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 を実行することができます。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説