2009. 4. 24. 15:02

DLL 제작 (Explicit)



DLL을 명시적(Explicit)으로 연결하기 위한 방법이다.
명시적(Explicit) 연결이라는 부분에 대해서는 프로그램이 실행되고 있는 도중에 필요한 함수가 포함된 DLL을 로드하는 방식이라고 보면 될 듯하다.

명시적인 연결을 위한 DLL을 제작할 때 중요한 함수들이 있다.
HINSTANCE LoadLibrary(LPCTSTR lpLibFileName);
지정한 DLL을 메모리로 읽어와 현재 프로세스의 주소공간에 맵핑시켜 사용할 수 있도록 한다. 하지만, 이미 다른 프로세스에서 해당 DLL을 사용하고 있다면, DLL을 메모리로 또다시 올리는 것이 아니고 DLL 의 사용 카운트만 1 증가시킨다.
인수는 읽고자 하는 DLL 의 파일 이름이다. 파일의 경로를 지정할 수도 있고, 지정하지 않을 수도 있다. 파일의 경로를 지정하지 않으면 DLL을 찾는 순서에 따라 경로를 뒤져가며 해당 DLL을 찾게 된다.

FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
DLL에서 엑스포트한 함수의 번지를 찾아 그 함수의 함수 포인터를 리턴한다.
첫 번째 인수는 함수가 포함된 DLL의 모듈 핸들이며 LoadLibrary() 가 리턴한 값이다.
두 번째 인수는 찾고자 하는 함수 이름이다.
이 함수가 리턴한 함수포인터를 사용하여 DLL에 있는 함수를 호출한다.

BOOL FreeLibrary(HMODULE hLibModule);
DLL의 사용 카운트를 1 감소시키며 사용 카운트가 0이 되었을 경우 메모리에서 DLL을 삭제한다.
첫 번째 인수는 LoadLibrary()가 리턴한 DLL의 모듈 핸들이다. LoadLibrary()로 DLL을 읽어왔다면 반드시 프로세스를 종료하기 전에 FreeLibrary()를 호출하여 DLL을 해제해야 한다.


DLL 제작
DLL 제작 방법은 아래를 참조하면 될듯.. -_-;;
http://todayis.tistory.com/206

DLL Test 프로그램(명시적 연결) 제작
새로운 Win32 프로젝트를 생성하고, WndProc 소스 부분을 아래와 같이 굵은 글자로 된 부분을 추가한다.
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    HINSTANCE hInst;
    int(*pFunc)(int, int);
    TCHAR str[128];

    switch (iMessage) {
    case WM_CREATE:
        hWndMain=hWnd;
        return 0;
    case WM_PAINT:
        hdc=BeginPaint(hWnd, &ps);
        hInst = LoadLibrary(L"DLL_test.dll");
        pFunc = (int(*)(int, int))GetProcAddress(hInst, "AddInteger");
        wsprintf(str, L"1+2 = %d", (*pFunc)(1, 2));
        TextOut(hdc, 10, 10, str, lstrlen(str));
        FreeLibrary(hInst);
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

컴파일.. 하고 실행을 하면.. 전에 설명했던 암시적(Implicit) 연결과 동일한 결과임을 알 수 있다.

단지 명시적 연결의 경우 원하는 위치에서 DLL을 직접 호출하는 구문이 있다는 것이다. 위의 경우에는 WM_PAINT
DLL을 사용하는 프로그램이 실행될 때 DLL이 같이 로드되는 것이 아니기 때문에 Settings에 따로 XXX.lib를 지정할 필요가 없다. 또 함수포인터로 함수가 있는 번지를 직접 조사한 후 그 주소를 이용하기 때문에 함수의 원형같은 것도 필요가 없다.
어떻게 보면, 명시적인 연결을 사용하는 DLL 이 더 쉬운듯 하다.

추가로 에러를 위한 처리구문을 추가하자.
LoadLibrary() 그리고 GetProcAddress() 등의 함수를 사용하는 부분을 아래와 같이 처리해 주면 된다.
if((hInst = LoadLibrary(L"DLL_test.dll")) == NULL) {
    MessageBox("There are no DLLs!!!");
    // 추가적인 에러 처리
    return 0;
}
if((pFunc = (int(*)(int, int))GetProcAddress(hInst, "AddInteger")) == NULL) {
    MessageBox("Where is The Function what I want to?? ");
    // 추가적인 에러처리
    return 0;
}


명시적(Explicit) 연결의 장점
1. 필요할 때만 DLL을 읽어와 사용하므로 메모리와 리소스가 절약된다.
2. 상황에 따라 사용할 DLL을 교체할 수 있다.
3. 필요한 DLL이 없는 경우라도 프로그램을 실행할 수는 있다. DLL을 사용하는 부분에서는 정상적인 동작을 안하더라도...
4. DLL을 호출하는 프로그램의 시작 실행속도가 빠르다.

명시적(Explicit) 연결의 단점
1. 사용하기 전에 DLL을 메모리로 읽어오므로 함수 호출 속도가 느리다.

  • 윈도우즈 API 완전정복 참고...


'Programmings > Windows Programming' 카테고리의 다른 글

GetModuleFileNameEx()  (0) 2009.05.15
DllMain  (0) 2009.04.27
DLL 제작 (Implicit 연결)  (0) 2009.04.23
DLL 이란...  (0) 2009.04.23
아스키 코드표  (0) 2009.03.03