Thinking Different





DLL(Dynamic Linking Library) 이란?
간단히 말해서 프로그램 컴파일안에 포함되지 않고 실행할때만 잠깐 로딩되어 실행되는 모듈의 집합체라고 할 수 있겠다.

 C++로 프로그램을 짜본 사람들은 컴파일을 하여 exe파일을 만들어본 경험이 있을것인데 이는 하나의 exe에 모든 코드를 적재하여 하나의 exe로 묶어서 만든것을 말한다. 

 DLL은 이런 하나의 EXE안에 들어가는 User 라이브러리 모듈(각각의 함수나 기타 기능을 가지는 함수들)을 DLL의 형태로 제공하여, exe를 가볍게 만들고 프로그램 실행시에 이 DLL을 exe가 참조되도록만 하는 기능이 DLL이라고 할 수 있다.

 DLL의 장점은 유지관리가 편리하다는 것이다.
예를 들어 FTP 프로그램을 만들어서 배포했다고 하자...  제작자는 DLL파일들을 각각 접속 및 다운로드 DLL, 유지 및 업데이트DLL, 기타 기능 DLL 뭐 이런식으로 만들어서 EXE와 함께 배포를 했는데 추후 다운로드 기능에 문제가 있어 패치를 해야 될 경우에 해당되는 다운로드DLL파일만 수정하여 그 파일만 업데이트로 배포하면 간단하다는 장점이 있다. 지극히 예를 들어 설명한 것이다. 파일용량이 클수록 DLL을 이용하여 제작하는것이 프로그램 유지관리에도 장점이다.


자 그럼 장황한 설명은 뒤로 하고 실전으로 DLL을 어떻게 만드는지 알아보자...  정말 간단하기 때문에 초보자도 그냥 이해할 정도로 손쉽게 만들 수 있다.

 해당 DLL 라이브러리 작성



위와 같이 win32 프로젝트를 생성후 빈 프로젝트로 DLL로 마침을 눌러 프로젝트를 생성한다.

1
2
3
4
5
6
7
extern "C" __declspec(dllexport)
void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

위와 같이 새 소스파일(*.cpp)를 만들어 입력후 컴파일하면 dll과 lib파일이 만들어진다. 위 소스는 간단히 2값을 받아서 서로 값을 바꿔주는 swap함수를 정의하였다.

extern "C" __declspec(dllexport) 함수명()
* __declspect(dllexport)
: dll파일에서 사용하는 함수라는것을 명시해주는 문장 (즉, 이 문장이 함수명 앞에 붙게 되면 컴파일러는 "이 함수는 DLL에서만 사용하는 함수야!"  라고 명시해주는 것이다)

* extern "C" : 네임맹글링을 방지합니다. 컴파일러 종류에 따라서 지맘대로 이름을 바꿔버리는 경향이 있습니다. 즉 c++ 컴파일러에서 컴파일을 했는데 c로 다시 컴파일 하면 이상한 문자를 붙혀서 원래 그대로의 함수명을 인식을 못할수가 있습니다. 위에서 보는 함수명은 swap입니다. 근데 컴파일러가 @LIJSFI#_swap 이런식으로 앞에 이상한것을 붙히게 됩니다. 이걸 방지하는 역할을 하게 됩니다.
DLL파일을 만들때는 반드시 위와같이 전체를 함수명 앞에 붙혀서 사용하시면 됩니다.


다음은 이 라이브러리를 이제 사용해 볼 때가 왔다.
새로운 프로젝트로 콘솔프로젝트를 만들고 아래와 같이 입력하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "stdio.h"
#pragma comment(lib, "dll_Exp.lib")
 
extern "C" __declspec(dllimportvoid swap(int *a, int *b);
 
int _tmain(int argc, _TCHAR* argv[])
{
    int a = 10;
    int b = 20;
 
    swap(&a, &b);
    printf("%d, %d\n", a, b);
 
    return 0;
}


프로젝트를 저장한다. 이제 바로 위에서 만든 라이브러리 파일2개(.dll, .lib)를 지금 작성한 프로젝트 폴더로 복사한다. (소스폴더 경로임)

#pragma comment(lib, "dll_Exp.lib")
lib 파일을 포함시키는 명령이다. 컴파일된 라이브러리의 lib파일을 해당 소스가 컴파일시에 컴파일러가 필요하기 때문이다. 반드시 문장 상위에 표시하여야 한다.

extern "C" __declspec(dllimport) void swap(int *a, int *b);
이 구문은 역시 DLL에서 export로 내보내는 것을 명시 하였다면 사용시에도 선언을 해주어야 사용이 가능하다. 함수명의 앞선 구문은 역시 이 함수는 DLL에서 사용되는 함수라는것을 명시해주는 것이다.
----------------------------------------------------------------------------------------------
extern "C" __declspec(dllimport) void swap(int *a, int *b);
extern "C" __declspec(dllimport)
void add(int *a, int *b);
extern "C" __declspec(dllimport) void sub(int *a, int *b);
만약 다수의 DLL 함수가 존재한다고 한다면 위와같이 해주어야 하지만 아래와 같이 간단히 묶어서 사용할 수 있다.

extern "C"
{
        void swap(int *a, int *b);
        void add(int *a, int *b);
        void sub(int *a, int *b);

}

또한 이 선언부 부분은 하나의 헤더파일로 보관하면 편리하게 사용 가능하다.




이제 컴파일을 해보자... 잘 실행되는것이 보인다....


자 어떤가 간단하지 않은가???

이제 간단하게 처리 모듈들은 따로 DLL로 관리하여 사용하면 편리하다... 

그리고 배포시에는 해당 EXE파일과 사용된 DLL파일만 묶어서 배포하면 된다.


DLL을 사용하는 방법에는 또 다른 방법이 존재한다. LoadLibrary(), GetProcAddress(), FreeLibrary()를 사용하는 방법인데..  이는 위 방법보다 사용하기 좀 불편한 감이 없지않아 있어서 해당 방법은 소개하지 않겠다.

필요하신분들은 구글링을 통해서 검색해 보시기 바란다....  위 방법도 별로 어렵지 않고 아주 간단하다.