DLL을 통한 기능 확장 - #1
진행중인 프로젝트에서 형식화된 텍스트 파일에서 아이템들을 읽어 들여 처리하는 루틴을
개발하게 되었다.
일반적으로 대부분의 아이템들이 사용되는데 이 프로젝트에서만 사용하는 하나의 아이템(HOLE)이 추가되었다.
그래서 이 하나의 아이템을 포함하는 DLL을 만들어 배포하는것이 아니라
일반적으로 사용되어지는 아이템을 처리하는 DLL하나(A.DLL) 그리고 이 하나의 아이템을 처리하는 DLL하나(B.DLL)를 만들어 제공하도록 계획을 세웠다.
B.DLL을 A.DLL과 함께 두면 A.DLL이 로딩될때 B.DLL을 찾아 있으면 B.DLL을 로딩하여
HOLE 아이템을 처리할 수 있게 되고 없다면 HOLE 아이템은 생략하게 된다.
그럼 로딩될때 자기가 있는 폴더에서 B.DLL을 찾아 로딩시키는 루틴을 보기로 하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
static void LoadPlugIns()
{
const static char _filter[]={"*.hhi"};
char _szPlugInsFilter[MAX_PATH]={'\0' ,};
char _szPlugInsPath[MAX_PATH]={'\0' ,};
char _szPath[MAX_PATH]={'\0' ,};
::GetModuleFileName(_hDllInstance,_szPath,MAX_PATH);
const int len=strlen(_szPath);
for(int i=len - 1;(i>=0) && ('\\' != _szPath[i]);i--);
if('\\' == _szPath[i]) _szPath[i] = '\0';
if(_szPath[strlen(_szPath) - 1] != '\\') strcat(_szPath,"\\");
strcpy(_szPlugInsFilter,_szPath);
strcat(_szPlugInsFilter,_filter);
/*
typedef struct _WIN32_FIND_DATA {
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwOID;
TCHAR cFileName[MAX_PATH];
} WIN32_FIND_DATA;
*/
WIN32_FIND_DATA FindFileData={0};
__plugins.clear();
HANDLE hFindFile = FindFirstFile(_szPlugInsFilter,&FindFileData);
if(hFindFile != INVALID_HANDLE_VALUE)
{
BOOL bTrue = TRUE;
do
{
strcpy(_szPlugInsPath,_szPath);
int len=strlen(_szPlugInsPath);
if(_szPlugInsPath[len - 1] != '\\') strcat(_szPlugInsPath,"\\");
strcat(_szPlugInsPath,FindFileData.cFileName);
HINSTANCE hInstDll = LoadLibrary(_szPlugInsPath);
if(hInstDll)
{
const unsigned int (* GetDataTypeMapCount)() = NULL;
DataTypeMap* (* GetDataTypeMap)() = NULL;
GetDataTypeMapCount = (const unsigned int (*)())GetProcAddress(hInstDll,"DllGetDataTypeMapCount");
GetDataTypeMap = (DataTypeMap* (*)())GetProcAddress(hInstDll,"DllGetDataTypeMap");
const unsigned int siz = GetDataTypeMapCount();
DataTypeMap* pDataTypeMap = GetDataTypeMap();
if(NULL != pDataTypeMap)
{
CDataTypeMapEntry* pDataTypeMapEntry = CDataTypeMapEntry::GetInstance();
pDataTypeMapEntry->RegisterDataTypeMap(siz , pDataTypeMap);
}
}
bTrue = FindNextFile(hFindFile,&FindFileData);
}while(TRUE == bTrue);
FindClose(hFindFile);
}
}
실제 예에서는 확장자를 .DLL로 하지 않고 .hhi로 두었다.
회색 바탕의 부분은 DLL을 로딩하여 DLL에 포함된 함수들을 구하는 부분이다.
HOLE 아이템을 처리할 수 있는 클래스를 생성하는 함수을 구하여 맵에 추가시킨다.
물론 DLL이 내려질때 로딩한 DLL들을 해제시켜줘야 하는것을 잊지 말기 바란다.