동적 라이브러리를 보기 전에 정적 라이브러리를 먼저 살펴 보겠습니다.
O 정적 라이브러리(.LIB)
정적 라이브러리(lib)를 만드는 법은 간단합니다. Visual Studio 2008에서 프로젝트 구성 형식을 정적 라이브러리(.lib)로 만들고 실행을 하면 되기 때문입니다. 이용을 하려면 이 라이브러리(.lib)와 해더 파일(.h)을 이 라이브러리를 이용할 프로젝트에 추가해주면, 이용 또한 쉽습니다.
- 프로젝트에 추가 방법 [첫번째]
1. [프로젝트 - 속성] 선택
2. [링커 - 일반]탭을 선택 후, '추가 라이브러리 디렉터리'에 lib 파일의 경로를 추가.
3. [링커 - 입력]탭을 선택 후, '추가 종속성' 란에 lib 파일을 입력하고, 확인을 누름.
- 프로젝트에 추가 방법 [두번째]
1. main.cpp(App 소스코드를 말함)에서 아래와 같이 입력합니다.
#pragma comment(lib, "XXX.lib") // lib경로를 입력해야한다. 속성창에서 하는 일과 같다.
void main()
{
......
}
O 동적 라이브러리(.DLL)
동적 라이브러리 또한 정적 라이브러리와 같이 사용이 가능합니다. dll로 프로젝트를 만들고 실행을 하게 되면 dll과 lib 파일이 생성됩니다. 여기서 lib파일에는 dll에 구현된 함수를 찾을 수 있는 정보가 있습니다.(저두 본거라...) 그래서 정적 라이브러리와 같은 방법으로 사용이 가능합니다. 이런 방식을 '암시적 연결'이라고 합니다.
암시적 연결 방법만 있는 것은 아닙니다. 명시적 방법 또한 있습니다. 이 방법은 dll 파일만 있어도 사용 할 수 있습니다. 하지만 C스타일의 함수여야 하는 듯 합니다. 아래를 보시면 아시겠지만 함수의 이름으로 주소를 얻어오기 때문에 C++에서 사용 할 수 있는 오버로딩이 되지 않습니다. 오버로딩이란 함수의 이름은 같지만 매개변수가 다를 경우 다른 함수로 간주 하는 것을 말합니다.
한번 코드로 정리 해보겠습니다. 첫번째는 헤더와 lib파일을 이용해서 dll을 사용하는 방법입니다.
- DLL 소스코드
#ifndef __SWAP_H__
#define __SWAP_H__
#ifdef DLL_EXPORT
#define DLLTYPE __declspec(dllexport)
#else
#define DLLTYPE __declspec(dllimport)
#endif //DLL_EXPORT
extern "C" DLLTYPE void SwapInt(int* dest, int* src);
extern "C" DLLTYPE void SwapStr(char* dest, char* src, int size);
#endif //__SWAP_H__
#define DLL_EXPORT
#include "Swap.h"
void SwapInt(int* dest, int* src)
{
int temp = *dest;
*dest = *src;
*src = temp;
}
void SwapStr(char* dest, char* src, int size)
{
char* pcTemp = new char[size];
for(int i = 0 ; i < size ; i++)
{
pcTemp[i] = dest[i];
dest[i] = src[i];
src[i] = pcTemp[i];
}
delete [] pcTemp;
}
- App 소스코드1 (.h + .lib 이용하여 dll 함수 호출)
#include <windows.h>
#include <tchar.h>
#include "..\SwapDll\Swap.h"
#pragma comment(lib, "..\\Debug\\SwapDll.lib")
int main()
{
int a = 10, b = 20;
SwapInt(&a,&b);
printf("swap --> \ta : %d, b : %d\n", a, b);
return 0;
}
- App 소스코드2 (WinAPI를 이용하여 dll 함수 호출)
#include <windows.h>
#include <tchar.h>
typedef void (*Func)(int*, int*);
int main()
{
int a = 10, b = 20;
HINSTANCE hDll = LoadLibrary(_T("SwapDll.dll"));
if(hDll == NULL)
{
printf("dll 로드 실패\n");
return -1;
}
Func pFunc = (Func)GetProcAddress(hDll, "SwapInt");
Func pFunc1 = (Func)GetProcAddress(hDll, "SwapStr");
printf("\t\ta : %d, b : %d\n", a, b);
pFunc(&a,&b);
printf("swap --> \ta : %d, b : %d\n", a, b);
FreeLibrary(hDll);
return 0;
}
위의 소스코드는 코드 작성 이외의 다른 설정은 하지 않았습니다. dll의 구현은 함수 단위로 되어있습니다.
dll을 클래스 단위로 구현한다면 어떻게 사용해야 할까요? 코드로 보겠습니다.
- DLL 소스코드(Class)
#ifndef __SWAP_CLASS_H__
#define __SWAP_CLASS_H__
#ifdef DLL_EXPORT_CLASS
#define DLLTYPE __declspec(dllexport)
#else
#define DLLTYPE __declspec(dllimport)
#endif //DLL_EXPORT_CLASS
class DLLTYPE CSwapClass
{
public:
CSwapClass();
~CSwapClass();
void Int(int* dest, int* src);
void String(char* dest, char* src, int size);
};
#endif //__SWAP_CLASS_H__
#define DLL_EXPORT_CLASS
#include "SwapClass.h"
CSwapClass::CSwapClass()
{
}
CSwapClass::~CSwapClass()
{
}
void CSwapClass::Int(int* dest, int* src)
{
int temp = *dest;
*dest = *src;
*src = temp;
}
void CSwapClass::String(char* dest, char* src, int size)
{
char* pcTemp = new char[size];
for(int i = 0 ; i < size ; i++)
{
pcTemp[i] = dest[i];
dest[i] = src[i];
src[i] = pcTemp[i];
}
delete [] pcTemp;
}
- App 소스코드 (Class)
#include <windows.h>
#include <tchar.h>
#include "..\SwapClassDll\SwapClass.h"
#pragma comment(lib, "..\\Debug\\SwapClassDll.lib")
int main()
{
int a = 10, b = 20;
CSwapClass swaper;
printf("\t\ta : %d, b : %d\n", a, b);
swaper.Int(&a,&b);
printf("swap --> \ta : %d, b : %d\n", a, b);
return 0;
}
위와 같이 사용한다면 class 또한 사용이 가능합니다. 만약에 암시적으로 사용하고 싶다면, LoadLibrary() 함수와 GetProcAddress () 함수를 사용해야 하야 합니다. 하지만 GetProcAddress() 함수에 들어가는 두번째 매개변수는 함수명 또는 서수가 들어가야 합니다. C++의 함수는 사용 할 수 없기 때문에 [extern "C"] 를 사용해야 합니다. 그래서 그 함수에서는 new CSwapClass()를 반환한다면 사용이 가능합니다.
※ 암시적 연결을 사용해서 함수 호출을 할려했더니 저는 애러는 나지 않았는데 정확한 주소
를 못 얻어오더군요.. 좀 더 공부를 해봐야 할 듯 합니다.
지금까지 암시적/명시적 연결로 DLL을 사용하는 방법을 알아봤습니다. 모두 열공하세요.
ps. Error C2491이 발생하신 분은 한번 보시기 바랍니다.(Microsoft 영문)
링크 : http://support.microsoft.com/kb/815647/en-us/
'프로그래밍 > C , C ++' 카테고리의 다른 글
[C/linux] UDP Serve/Client socket programming Example (0) | 2012.06.18 |
---|---|
[C/linux] TCP Serve/Client socket programming Example (0) | 2012.06.18 |
__stdcall 쓸때 (0) | 2012.04.16 |
명령어로 라이브러리 만들기 (0) | 2011.09.29 |
*.lib 와 *.dll 파일의 차이점 (0) | 2011.09.29 |