1. 파일 -> 새로만들기 -> 프로젝트 -> Visual C++ -> Win32 -> Win32 콘솔 프로젝트 선택
- 솔루션 이름과 프로젝트 이름 설정
- 여기서는 솔루션 이름은 DLLEX라 하고, 프로젝트 이름은 DLLEX_Client라 한다.
2. Win32 응용 프로그램 마법삽가 뜨는데, 탭란에 "응용 프로그램 설정" 부분을 누른다.
3. Radio 박스로 된 DLL을 선택하고, 체크박스로 된 내보내기 기호란을 체크한 후 "마침" 버튼을 누른다.
4. 그러면, 소스파일에는 stdafx.cpp, DLLEX_Client파일이 생성이 되고,
헤더 파일에는 stdafx.h, DLLEX_Client.h 파일이 생성이 된다.
5. 아래는 프로젝트 생성 후 구성된 DLLEX_Client.cpp 파일을 나타내었다.
// DLLEX_Client.cpp
#include "stdafx.h"
#include "DLLEX_Client.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// 내보낸 변수의 예제입니다.
DLLEX_CLIENT_API int nDLLEX_Client=0;
// 내보낸 함수의 예제입니다.
DLLEX_CLIENT_API int fnDLLEX_Client(void)
{
return 42;
}
// 내보낸 클래스의 생성자입니다.
// 클래스 정의를 보려면 DLLEX_Client.h를 참조하십시오.
CDLLEX_Client::CDLLEX_Client()
{
return;
}
6. 아래는 프로젝트 생성 후 구성된 DLLEX_Client.h 파일을 나타내었다.
// DLLEX_Client.h
#ifdef DLLEX_CLIENT_EXPORTS
#define DLLEX_CLIENT_API __declspec(dllexport)
#else
#define DLLEX_CLIENT_API __declspec(dllimport)
#endif
// 이 클래스는 DLLEX_Client.dll에서 내보낸 것입니다.
class DLLEX_CLIENT_API CDLLEX_Client {
public:
CDLLEX_Client(void);
// TODO: 여기에 메서드를 추가합니다.
};
extern DLLEX_CLIENT_API int nDLLEX_Client;
DLLEX_CLIENT_API int fnDLLEX_Client(void);
7. 이 헤더파일에서 빨간색으로 된 부분을 제거한다. 그런 후 예를 들어보자. 하나의 "funct"라는 함수를 만든다
#ifdef DLLEX_EXPORTS
#define DLLEX_API __declspec(dllexport)
#else
#define DLLEX_API __declspec(dllimport)
#endif
class Interface
{
public:
virtual ~Interface(void) {}; // 소멸자를 만들어 준다.
virtual int funct(void) = 0; // 예. 함수를 만들어 준다.
};
extern "C"
{
DLLEX_API Interface* CreateInterface(void); // Create 해준다.
DLLEX_API void DestroyInterface(Interface* pInterface); // Destory 해준다.
};
8. 이렇게 헤더파일(DLLEX_Client.h)을 구성이 되었다면 소스파일(DLLEX_Client.cpp)을 수정해준다.
* "DLLMain" 부분을 건들 필요가 없다.
class InterfaceImpl : public Interface
{
public:
InterfaceImpl(void)
{}
virtual ~InterfaceImpl(void)
{}
public:
virtual int funct(void)
{
return 100;
}
};
DLLEX_API Interface* CreateInterface(void)
{
return (Interface*)new InterfaceImpl;
}
DLLEX_API void DestroyInterface(Interface* pInterface)
{
InterfaceImpl* pI = reinterpret_cast<InterfaceImpl*>(pInterface);
delete pI;
}
9. 컴파일(F7) 해준다. 컴파일 하면 Debug나 Release 폴더에 "DDLEX_Client.DLL" 파일이 생성이 될 것이다.
10. 그럼 그 DLL 파일을 가지고 다른 프로젝트에서 불러본다. Consol 프로젝트를 열어서 작업한다.
(차후에 배포시나 다른 회사에 넘겨줘야될 상황이 된다면 DLL과 .h 파일을 넘겨주고
관련된 함수 목록과 설명을 넘겨주면 된다)
11. 이제 "DLLEX" 라는 콘솔 프로젝트를 열어서 main.cpp와 main.h 파일을 생성해준다.
12. main.h 파일에는 아래의 내용을 추가 한다.
//main.h
#pragma once
#include <Windows.h>
extern "C"
{
class Interface
{
public:
virtual ~Interface(void) {}; // 다른 DLL만들었을 때 그 DLL의 소멸자를 만들어준다.
virtual int funct(void) = 0; // 사용자 함수 추가할 때
};
typedef Interface* (*fnCreateInterface)(void);
typedef void (*fnDestroyInterface)(Interface* pInterface);
};
// 마찬가지로 아래도 다른 DLL을 추가시 아래와 같은 방식으로 추가만해주면 된다.
class InterfaceLoader
{
public:
InterfaceLoader(void)
:hDllHandle_(NULL),
fpCreateInterface_(NULL), fpDestroyInterface_(NULL), pInterface_(NULL),
bIsCreated_(false)
{}
~InterfaceLoader(void)
{
DestroyInterface();
}
public:
bool CreateInterface(void)
{
do
{
if (bIsCreated_) break;
hDllHandle_ = LoadLibrary("DLLEX.dll");
if (hDllHandle_ == NULL) break;
fpCreateInterface_ = (fnCreateInterface)GetProcAddress(hDllHandle_, "CreateInterface");
if (fpCreateInterface_ == NULL) break;
fpDestroyInterface_ = (fnDestroyInterface)GetProcAddress(hDllHandle_, "DestroyInterface");
if (fpDestroyInterface_ == NULL) break;
bIsCreated_ = true;
return true;
} while(0);
if (hDllHandle_ != NULL) FreeLibrary(hDllHandle_);
hDllHandle_ = NULL;
fpCreateInterface_ = NULL;
fpDestroyInterface_ = NULL;
return false;
}
bool DestroyInterface(void)
{
do
{
if ( !bIsCreated_ ) break;
if ( (pInterface_ != NULL) ) fpDestroyInterface_(pInterface_);
if ( hDllHandle_ != NULL ) FreeLibrary(hDllHandle_);
hDllHandle_ = NULL;
fpCreateInterface_ = NULL;
fpDestroyInterface_ = NULL;
pInterface_ = NULL;
bIsCreated_ = false;
return true;
} while(0);
return false;
}
Interface* getInterface(void)
{
if (pInterface_ == NULL)
{
if (!bIsCreated_)
if (!CreateInterface()) return NULL;
pInterface_ = fpCreateInterface_();
}
return pInterface_;
}
private:
HINSTANCE hDllHandle_;
fnCreateInterface fpCreateInterface_;
fnDestroyInterface fpDestroyInterface_;
Interface* pInterface_;
bool bIsCreated_;
};
13. main.cpp 파일에는 아래의 내용을 추가 한다.
#include <iostream>
#include "main.h"
int main(int argc, char** argv)
{
InterfaceLoader loader;
std::cout << loader.getInterface()->funct() << std::endl;
return 0;
}
14. 결과 - 100 출력
'컴퓨터공학 기초 > C.C++' 카테고리의 다른 글
STL - vector와 관련 함수 (0) | 2011.09.16 |
---|---|
자주 사용하는 C++ STL algorithm 함수 정리 (0) | 2011.09.16 |
[DLL] DLL 만드는 방법 1 (0) | 2011.09.08 |
cout 출력 포맷 설정하기 (0) | 2011.07.28 |
쓰레드(pthread_create, pthread_join) (0) | 2011.04.03 |