본문 바로가기
Development/C & C++

DLL

by nickeys 2011. 5. 9.
# 정적 라이브러리(Static Library)
=> 정적 라이브러리로 설정된 프로젝트의 결과물은 .Lib파일로, 이 파일 내부에는 순수 코드만 들어 있다.
만약 한글 출력 관련 정적 라이브러리를 만들었다면(Han.Lib파일이 그 결과물이라 치자), 라이브러리 파일과 클라이언트
측에서 함수를 호출 하기 위해 헤더파일을 프로젝트에 포함 시키고 빌드하게 되면, .Lib파일 내용이 목적코드에
복사가 되어 실행파일이 나온다. 따라서, 빌드를 위해 포함 시켰던 두 파일은 실행 파일에서는 필요가 없게 된다(stand alone).

# 동적 라이브러리(Dynamic Library)
개요=> .dll파일의 장점으로,
1. 모듈화가 되므로 유지 보수가 쉽고(디버깅이 쉬움) 분담 작업이 가능하다.
2. 모듈들을 분리해서 관리하므로 다른데서 가져다가 사용하기에 용이 하다. 따라서, 코드 재사용성이 높다.
3. 하나의 .dll파일만 로드하고 여러 프로그램에서 공유가 가능하므로 메모리가 절약된다.
4. 모듈들이 다 .dll파일로 분할되므로 파일 자체의 크기가 작아진다.
5. .dll파일에는 함수 뿐만 아니라 리소스도 같이 포함 될 수 있는데 리소스를 .dll파일로 분리 해 두었다가 상황에 맞게 알맞은 리소스 파일을 로드해서 사용 가능하다.
6. 혼합 프로그래밍에 용이하다.
등이 있겠다. 반면에 .dll파일은 실행 파일과 분리 되어 있으므로, .dll파일과의 관계에서 생기는 프로그램 에러를 잡아낼 수 없다. 이 말은 정적으로는 .dll파일이 없어도 아무런 에러가 발견되지 않는 다는 문제와 .dll파일의 에러가 있을 경우는 디버깅이 힘들다는 문제가 생긴다는 것이다.

+@ Win32 API함수들도 대부분 .dll포맷으로 작성되어 있다(심지어 디바이스 드라이버 파일, .drv, 도 일종의 .dll 파일이다).

# DLL 관리
 .dll파일은 한번 로드 되면 프로그램들이 공유해서 사용한다. 하지만, 이렇게 사용 되는 것은 코드의 경우고 데이터의 경우는 각 프로그램마다 독립적으로 가져야 하므로 데이터는 각각의 프로그램이 따로 할당해서 쓴다. 로드된 .dll은 개략적으로 카운팅 방식으로 해제를 한다. 무슨 말이냐면, .dll파일을 사용하는 프로그램이 몇 개인지 카운팅을 해서 0이 됐을 때 해제를 한다는 의미이다.

# 접속
 __declspec
=> __declspec(extended-attribute) 대상
extended-attribute는 .dll과 관련해서 dllimport 와 dllexport를 사용하는데,
전자는 DLL에 있는 데이터, 오브젝트, 함수를 사용하겠다는 선언을 말하고
후자는 DLL에 있는 데이터, 오브젝트, 함수에 대한 정보를 클라이언트에게 제공하겠다는 선언 이다. 이렇게 DLL파일 내부의 대상을 노출할 경우는 DEF파일의 Export란에 명시할 필요가 없으며 __export 키워드를 대체하게 된다.

extern "C"
=> C++이 공개하는 함수의 정보를 mangled name이라고 하며, 이런 식으로 공개된 함수는 C++이외의 다른 언어에서는 사용이 불가하다. 이 키워드는 mangled name을 만들지 않게 함으로써 C형식으로 함수의 정보를 공개 하도록 한다.

결론=> DLL에서 export되는 함수는 다음과 같이
extern "C" __declspec(dllexport) 함수 원형;
클라이언트에서는 다음과 같이
extern "C" __declspec(dllimport) 함수 원형;

+@ 위와 같은 선언을 함수가 많아지면 일일이 하기 힘들다. 이럴 때 사용할 수 있는 Tip~
#ifdef DLLEXPORT
#define DLLTYPE __declspec(dllexport)
#else
#define DLLTYPE __declspec(dllimport)
#endif
이렇게 .dll파일의 헤더에 선언을 하게 되면, 해당 헤더파일을 포함 하기 전 DLLEXPORT를 선언하게 되면 DLLTYPE이 __declspec(dllexport)로 정의 될 것이고, 아니면 __declspec(dllimport)로 정의될 것이다.

+@ 빌드 시에 경로 참조 우선순위
1) 프로그램이 포함된 디렉토리
2) 프로그램의 현재 디렉토리
3) 윈도우즈 시스템 디렉토리
4) 윈도우즈 디렉토리
5) PATH 환경 변수가 지정하는 모든 디렉토리

# Import Library
=> 이 파일에는 DLL파일이 export하는 함수의 정보와 위치 정보가 담겨 있다. 파일 이름은 .dll파일과 동일 하며, 확장자는 .lib이다. 직접적인 코드는 담겨 있지 않으므로, 빌드 시에만 필요하다. 컴파일 할 때 포함된 Import Library에서 함수와 .dll파일의 위치 정보를 링크 시키며 .h파일은 컴파일 시 함수의 원형을 제공하므로(또한 라이브러리 배포시 주석을 포함 시킴으로써 가이드 역할도 한다) Import Library, 헤더파일 2가지 파일이 빌드 시에 합쳐져서 실행파일이 만들어 진다(실행 시에는 실재 코드만 있으면 되므로 .dll파일만 있으면 됨). Import Library를 지정하는 방법으로는(암시적:Implicit 연결)
1) .lib파일을 프로젝트에 포함시킨다.
2) #pragma comment(lib, "*.lib") 구문을 이용한다.
3) 프로젝트 속성에서 링커/입력/추가 종속성 에 Import Library를 지정한다.
등이 있다.

# 명시적(Explicit) 연결
=> 앞서 암시적 연결과는 다르게, 실행 시간 중 필요할 때 선택적으로 DLL을 로드하는 방식. 함수가 속해있는 DLL파일의 이름을 명시적으로 지정하므로 Import Library가 불필요하다. 암시적 연결의 경우 프로그램이 시작될 때 DLL도 같이 메모리로 올라오므로 메모리를 더 먹는다.

'Development > C & C++' 카테고리의 다른 글

C++0x - rvalue reference <- 위키백과 내용을 번역.  (0) 2011.07.09
Memory in Windows system  (0) 2011.05.09