Windows_/Windows32_API

Windows :: 라이브러리와 DLL

sosal 2014. 7. 25. 23:18
반응형

/*

 * http://sosal.kr/

 * made by so_Sal

 */



1. 라이브러리
2. DLL
3. DLL Export, Import
4. import library



Library
:: Static Library 함수, 데이터, 자료형 등 여러가지 프로그래밍 요소의 집합.
일반적으로 Library를 말하면 Statc library. 정적 라이브러리를 말한다.

printf() 함수를 쓰기 위해서 #include<stdio.h> 헤더파일을 추가해보았을 것이다.
stdio.h :: extern int printf (__const char *__restrict __format, ...);
라는 구문이 있는데, 이 함수의 원형을 보자하면 끝이 없다.
이 굉장히 긴 코드를 단지 출력해주기 위해 매번 프로그램에 추가하는 것은
효율성에서 매우 뒤쳐진다.
따라서 위 printf()와같이 표준화 할 수 있는 함수들을 하나에 모아서
공유하면서 쓰기 위해 만들어진게 라이브러리이다.



" Library :: 도서관 " ::
책의 제목만 안다면 찾아내어 읽음으로써 그 내용을 쉽게 알 수 있다.
프로그래머 역시 공유 라이브러리에 만들어져 있는 함수들의 이름만 안다면
쉽게 프로그래밍 할 수 있다.


그림 - 공유 라이브러리와 사용자 코드로 이루어지는 프로그램들



위 그림에서 이해할 수 있듯 프로그래머가 User_Project.exe 라는 프로그램을
간단하고 빠르게 만들기 위해 Library.lib에 정의된 (Library.lib 라는 이름은 단순한 예)
함수를 가져와서 쓴다.

라이브러리 파일에 있는 함수와 데이터는 링커에 의해 실행파일에 그대로 옮겨지며
실행파일의 일부분이 되는데
, 이러한 라이브러리 연결 방법을 정적 링크 (Static Link)라 한다.
이 방법은 라이브러리의 코드를 컴파일시 실행파일에 모두 복사한다.

Win32 Static Library 프로젝트로 만들어진 헤더, 리소스의 함수, 자료및 변수들은
#include 전처리 명령어를 통해 모든 프로그램이 사용할 수 있다.




DLL :: Dynamic Link Library 동적인 라이브러리

정적 라이브러리는 모든 내용이 프로그램 안으로 들어가
라이브러리 소스와 프로그램 소스가 하나가 되어 하나의 객체가 되었다.

반면 동적 라이브러리는 프로그램과 하나가 되는것이 아니라,
프로그램이 필요할 때 동적 라이브러리에 있는 함수를 호출하는 방법이다.



그림 - 사용자가 만든 프로그램이 필요시 동적 라이브러리에 접근



User_project.exe 프로그램은 동적 라이브러리에 있는 함수의 정보만 포함되고
실제 함수는 복사하지 않았다. -> 프로그램의 용량이 작다.
함수가 필요하게 되면 Library.lib 를 찾아 함수를 실행하게 된다.


윈도우즈 API 함수들은 Windows.h 하나의 헤더파일에 대부분의 함수가 저장되어있다.
Win API를 통해 만들어지는 프로그램들 모두가 위 헤더파일을 포함하였을때,
필요이상으로 큰 용양을 차지하게 되어버린다.
그래서 API 함수 자체는 KERNEL32.DLL, GDI32.DLL 등 동적 라이브러리에 저장되어 제공한다.
이처럼 DLL 동적 링크 라이브러리는 윈도우에선 필수적이다.


DLL은 정적 라이브러리보다 사용하는것이 복잡하고 까다롭다.
하지만 한코드를 여러 프로그램이 동시에 사용하여 메모리가 절약되는 점.
용양이 작고, 실행파일만 읽어오면 되기 때문에 로딩 속도가 빠른점.
함수를 고치기 위해 프로그램에 접근하지 않고, DLL만 고치면 되어
성능 향상 및 수정에 대해서 자유로운점.
여러가지 언어가 쉽게 혼합될 수 있는 점 등 DLL은 윈도우에 있어서 필수적이다.





DLL이 가지고 있는 함수는 여러 프로그램이 공유가 되더라도 상관이 없다.
따라서 함수에 대한 영역은 메인 메모리에 한번만 로드하면 된다.

하지만, 프로그램이 DLL에 있는 변수에 접근한다면 이야기는 달라진다.
프로그램끼리 서로 같은변수에 접근하면 논리적으로 바람직하지 못한 결과를 가져온다.
이처럼 DLL 내부의 값을 기억하는 변수는 프로그램이 공유하도록 내버려두지 않고
각 프로그램마다 새롭게 메모리를 할당받는다.

DLL은 Usage count라는 것을 유지하여 DLL에 접근하고 있는 프로그램의 수를 세어
종료해야할 시점을 스스로 판단하여 메인 메모리에서 삭제하게 된다.





extern "C"
:: C++ 문법에서는 오버라이딩 기법을 통해 (매개변수의 다양화) 같은 이름을 가진
                     여러개의 함수를 생성할 수 있다.
                     이렇듯, C++ 문법에서 함수의 정보를 mangled name이라 하며, 이런 방식은
                     C, 파스칼 등에 혼용되지 않는다.
                     C++과 구분짓기 위해 사용하는 지명자이다.

DLL Export, Import

DLL에서 제공하는 함수 정보를 다른 프로그램들이 받아 실행할 수 있도록
함수정보를 프로그램에게 던져주는데, 이를 Export 이라 한다.

반면 프로그램에서 DLL에 있는 함수를 사용하기 위해 함수정보를 사용하겠다고 선언하는데,
이를 Import 라고 한다.

DLL에 존재하는 함수는 제공하는자의 Export 선언과, 받는자의 Import 선언이
서로 상응할 때 연결되게 된다.


__declspec :: 함수에 대한 정보를 제공하는 선언문
                    Export, Import 하기위한 함수 앞에 위 수식어가 필요하다.



예를 들어 BOOL swap(int* a, int* b) 이라는 함수를 동적 라이브러리로 만든다면
extern "C" __declspec(dllexport) BOOL swap(int* a,int* b);
extern "C" __declspec(dllimport) BOOL swap(int* a,int* b);







일반적인 프로그램에서 Import 선언을 하여 함수를 사용하려 한다면,
그 함수가 어떤 DLL에 있는지 알아야 한다. 하지만 import 선언에는
어떠한 DLL에 함수가 존재하는지 알려주지 않는다.
따라서 현재풀더, system 풀더, 환경변수에 등록된 풀더에 있는 모든 DLL을 열어
하나하나 확인해야하는 상황이 펼쳐진다. (물론 이런일은 없다.)

Import library
임포트 라이브러리는 DLL들을 담는 상자라고 봐도 좋다.
하나의 게임 프로젝트를 만든다면, 그에 필요한 DLL들을 만들고,
클라이언트는 DLL로부터 함수를 요청 할 것이다.
개발자 입장에서 매번 DLL을 불러오고, import 하는것은 매우 성가시다.
Import Library는 DLL들의 이름, DLL에서 정의하고있는 함수등의 정보를 포함한다.
DLL을 담는 상자라고 표현하면 좋겠다. (함수에 대한 정의만 존재할 뿐, 리소스는 DLL에 있다.)