Post

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들을 해제시켜줘야 하는것을 잊지 말기 바란다.