SW 개발

프로그래밍 - DLL의 기초개념 (사용하기 / 만들기)

. . . 2008. 12. 26. 23:26
반응형
  • 잡담
    • 포스팅 수정완료 (190821)

DLL이란?

By MSDN : http://msdn.microsoft.com/ko-kr/library/1ez7dh12(VS.80).aspx

DLL(동적 연결 라이브러리)은 여러 함수의 공유 라이브러리로 사용되는 실행 파일입니다. 동적 링크를 사용하여 프로세스에서 해당 프로세스의 실행 코드에 포함되지 않은 함수를 호출할 수 있습니다. 함수의 실행 코드는 DLL에 있으며, DLL에는 이것을 사용하는 프로세스와는 별도로 컴파일, 링크 및 저장되는 하나 이상의 함수가 포함되어 있습니다. DLL을 사용하여 데이터와 리소스를 쉽게 공유할 수 있습니다. 즉, 여러 개의 응용 프로그램이 메모리에 있는 하나의 DLL 복사본 내용을 동시에 액세스할 수 있습니다.

동적 링크는 DLL 함수의 실행 코드를 찾기 위해 런타임에 필요한 정보만을 실행 모듈(.DLL 또는 .EXE 파일)에 포함한다는 점에서 정적 링크와 다릅니다. 정적 링크에서는 링커가 정적 연결 라이브러리에서 참조되는 모든 함수를 가져와서 코드와 함께 실행 파일 안에 포함시킵니다.

정적 링크 대신 동적 링크를 사용하는 데에는 몇 가지 장점이 있습니다. DLL을 사용하면 메모리 절약, 스와핑 감소, 디스크 공간 절약, 용이한 업그레이드, 출시 후 지원 제공, MFC 라이브러리 클래스를 확장할 수 있는 메커니즘 제공, 여러 가지 언어 형식의 프로그램 지원, 용이한 국가별 버전 생성 등의 잇점이 있습니다.

DLL의 링크

DLL을 링크하는 방법은 Implicit 링킹과 Explicit 링킹 두가지 방법이 있습니다.

Implict 링킹 (암시적링크)

Imolict 링킹은 프로그램이 시작되면서 해당 DLL을 바로 로드하는 방법입니다.

DLL 안에는 DLL 안에 있는 함수들이 무엇인가를 알려주는 함수형을 기록하고 있습니다. 이 함수들이 메인 프로그램에서 호출되면 메인 프로그램의 실행 주소안에서 같이 링크되어 돌아갑니다. DLL을 열어서 읽어보면 함수명만있지 인자들은 전혀 기록이 되어있지 않기 때문에 이 인자를 맞춰주기 위해 DLL과 함께 헤더파일과 LIB파일이 필요합니다.

헤더 파일은 보통 *.h 로 구성된 파일로 DLL 안에 들어있는 함수에 대한 설정을 합니다.

DLL이 있어서 바로 동적 링크되는데 LIB 파일이 왜 필요한가?

이유는 메인프로그램을 컴파일하고 링크할때 DLL안에 있는 함수들은 메인 프로그램에 있는 어느것과도 링크되지 않아 실행 파일로 만들때 에러가 나기때문입니다.

DLL로 PaintImage(LPSTR filename) 이라는 함수를 만들어놓고 메인 프로그램에서 쓰려고한다. 메인프로그램의 해더에 extern "C" \_desclspec(dllimport)void PaintImage(LPSTR filename); 위와 같이 정의해놓고 컴파일을 하려고 하면 링크할때 파일을 찾을수 없다고 할것이다.

위와 같은 에러를 pass 하기 위해서.. 가상으로 PaintImage(LPSTR filename) 를 만들어 그것을 0으로 설정해주는 함수가 있어야 합니다.

  void PaintImage(LPSTR filename) = 0;

이렇게 만들어진 함수가 컴파일되어 LIB 파일로 만들어집니다. 따라서 메인 프로그램에서는 실행 내용이 아무것도 들어있지 않은 LIB를 프로젝트에 삽입하고 컴파일 하는것입니다. 그런후 프로그램이 실행되면 LIB에 설정된 파일명에 따라 DLL을 로드하고 프로그램 메모리 안에 DLL에서 로드시킨 모듈을 삽입 시킵니다.

결론적으로 Implict 링킹방식의 DLL을 이용하여 프로그램을 작성할때 필요한것들..

  • 실절적으로 프로그램이 실행될때 로드되는 파일 (*.DLL)
  • 컴파일할때 설정해주는 파일명이 들어있는 해더파일 (*.H)
  • 링크할때 메인 프로그램에 빈 함수를 설정하는 LIB 파일(*.LIB)

Explicit 링킹 (명시적링크)

Explicit 링킹이란 Implict 링킹처럼 세가지의 파일이 필요없이 단순하게 DLL을 이용하여 로드할수있는 방법을 의미합니다. 이 방법으로 DLL을 로드할 경우 세개의 함수를 이용합니다.

라이브러리를 로드하는 함수

HMODULE WINAPI LoadLibrary( \_\_in LPCTSTR lpFileName );

LoadLibrary()를 이용하여 로드하면 인스턴스 핸들이 리턴됩니다.

인스턴스 핸들을 이용하여 필요한 함수포인터를 찾는 함수

FARPROC WINAPI GetProcAddress( \_\_in HMODULE _hModule_, \_\_in LPCSTR _lpProcName_ );

라이브러리를 해제하는 함수

BOOL WINAPI FreeLibrary( \_\_in HMODULE hModule );

DLL의 제작과 사용

정규 DLL

정규 DLL 이란 C언어로 작성하여 C언어 함수를 호출할수 있는 DLL을 만드는것입니다. 정규 DLL로 만들면 외부에서 이 DLL 함수를 호출할경우 C 언어로 설정된 함수만 호출할 수 있습니다. 즉, 클래스 자체는 정규 DLL에서 호출할수 없습니다.

정규 DLL 만들기

  • vs에서 정규 DLL 만들기 (프로젝트 만들때 옵션)
    • Regular DLL with MFC statically linked : LIB 형태로 링크하여 DLL을 만든는것
    • Regular DLL using shared MFC DLL : DLL 형태로 연결하는것
    extern "C" \_\_declspec(dllexport) Type FuncName()
    {
         // 생략
    }
    // extern "C" \_\_declspec(dllexport)  를 앞에 적어야 dll 외부에서 호출하여 사용할수있는 함수가 된다.

위와 같이 만들면.. dllName.dll / dllName.lib 두개의 파일이 생성될것이다.

정규 DLL 사용하기

  1. 프로젝트 세팅에서 위에서 생성한 lib 파일을 포함시킨다.
  2. DLL에서 선언한 함수명과 같게 함수선언 : extern "C" \_\_declspec(**dllimport**) Type FuncName(); dllimport / dllexport 와 같이 인자가 틀리다
  3. 사용한다. (예제)
//dll에 있는 int Factory(int num) 과 같은 형태의 함수를 typedef로 설정한다.

typedef int (*FactoryFunc)(int num);

//typederf로 설정된 FactoryFunc의 변수를 설정한다.

FactoryFunc lpFactoryFunc;   //Dll 인스턴스 핸들 설정
HINSTANCE hDll;              //Dll를 로드한다.

hDll=LoadLibrary("ExRegularDll.dll");

if(hDll==NULL)
{
    AfxMessageBox("ExReqularDll이 없습니다.");
    return;
}

lpFactoryFunc=(FactoryFunc)GetProcAddress(hDll,"Factory");  //함수를 얻는다.

if(lpFactoryFunc==NULL)
{
    AfxMessageBox("Factory 함수가 없습니다. ");
    return;
}
int num=lpFactoryFunc(2);

FreeLibrary(hDll);     //DLL 해제

확장 DLL 만들기 / 사용하기

확장DLL은 C++ 로 DLL을 만들 수 있는 형태입니다. 즉 클래스를 라이브러리로 사용하고 호출할 수 있는 형태로 제작된 DLL 입니다. 확장 DLL은 MFC 전용 DLL을 만들때 주로 사용합니다. Visual C++ 에서 모듈화할때 주로사용합니다. 쓰는 방법은 클래스 명 앞에 AFX_EXT_CLASS 를 설정한후 그냥 DLL 을 만듭니다.

  class SampleDlg : puplic CDialog
  // class AFX\_EXT\_CLASS CExDllDlg : public CDialog

위와 같이 하고.. 프로젝트 설정에서 lib 파일을 포함시켜서 일반적인 클래스 사용하듯이 사용한다.

반응형