본문 바로가기
Programming/Tips(C++,C#)

Chapter 6. Dynamic Linking Library

by 곰네Zip 2014. 10. 27.

*이 포스팅은 개인 학습을 위해 내용을 정리한 것이 목적입니다.

 

1. DLL의 기초

  - DLL로딩하는 과정

    DLL을 regsvr32를 이용하여 등록 후, 클라이언트에서 이 레지스트리에 등록된 DLL을 메모리로 로딩함.

  1) DLL의 특징

    DLL은 로딩하는 프로세스의 같은 주소 공간을 사용한다. 다른 프로세스 간에는 다른 물리적 메모리 주소를 사용하고 있으므로, 다른 프로세스간 접근은 프로세스간 통신을 이용하여야 한다.

    *DLL을이 무엇이고 이를 이용하여 가능한 작업

     - 디스크상의 파일로서 글로벌데이터, 컴파일된 함수, 프로세스의 일부분이 되는 리소스로 구성

     - 컴파일 되면 기본 주소에 DLL이 로드되고, 다른 DLL과 충돌하지 않으면 프로세스에서 동일한 가상주

      소에 매핑됨

     - export된 다양한 함수들을 가지고 있고, 클라이언트는 이 함수들을 import. DLL로딩시에 매칭됨

     - 소프트웨어의 모듈화를 가능하게 함

     - 모듈화를 이루면 내용 변경시, 모듈의 개별적인 수정과 테스트가 가능해짐

     - Win32에서 각 프로세스는 자신만의 DLL 읽기/쓰기 글로벌 변수의 복사본을 갖는다. 프로세스간에 메

       모리 공유를 원하면 메모리 맵 파일을 사용하거나 공유 데이터 섹션을 사용하여야 함.

     - DLL이 힙 메모리를 요구할 때마다 클라이언트 프로세스의 힙 영역에 메모리가 할당됨

     - Win32에서 DLL코드는 여러 프로세스들이 공유하지만 DLL이 사용하는 데이터 영역은 각 프로세스별로

      할당된다. DLL이 사용하는 데이터 중 다른 프로세스와 공유하기 위해서는 메모리 맵 파일 또는 DLL의

      모듈정의파일에 섹션을 설정해야한다.

     - 종류 : MFC일반DLL, MFC확장DLL

     - 연결방법 : 명시적링크, 암시적링크

 

   *DLL함수의 시작 - DllMain  

 BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)

     i) DLL_PROCESS_ATTACH

      DLL이 로딩될 때 보내지는 메시지.

     ii) DLL_PROCESS_DETACH

      DLL이 메모리에서 해제될 때 보내지는 메시지.

 

2. 간단한 DLL실습

  1) DLL생성

    -export 함수 정의파일 만들기 

 ;DllTest.def

LIBRARY     "DllTest.dll"

DESCRIPTION 'blabla'

 

EXPORTS

        FunctionName                 @2  PRIVATE

     위 FunctionName은 export시킬 함수로 구현해야 하며, @뒤의 숫자는 유일해야함(중복시 컴파일에러)

 

 

  2) 명시적 연결을 이용한 클라이언트 만들기

    - 명시적 연결을 위해서는 LoadLibrary("dll이름");으로 로드하면 된다.

 

3. 컴포넌트의 분리

  - DLL컴포넌트를 분리하면 CreateInstance()를 사용할 수 없게 되었다. 그러나 DLL에서 이 함수를 export하여주므로, 이것을 이용한다. 아래의 MyCreateIntance()는 CreateInstance()역할을 하는 함수 

   - MyCreate.h 

 IUnknown* MyCreateInstance(char* name);

   - MyCreate.cpp

 #include <iostream>

 #include <unknwn.h>

 #include "MyCreate.h"

 typedef IUnknown* (CALLBACK *CREATEPROC)(); //함수포인터 사용을 위한 define

 

 IUnknown* MyCreateInstance(char* name){

    HINSTANCE hIns = ::LoadLibrary(name);

    if(hIns == NULL){ return NULL; }

    CREATEPROC CreateInstance =(CREATEPROC)::GetProcAddress(hIns,"CreateInstance");

    if( CreateInstance == NULL){ return NULL; }

    return CreateInstance();

 }

  - 여기에서 MyCreate.h를 만들었는데, IUnknown을 사용하기 위해서는 <unknwn.h>를 포함하여 주자. 그리고 이전까지 CreateInstance함수 호출부는 MyCreateInstance로 변경되어야 하고, DLL 서버에 있는 인터페이스 정의파일과 GUID를 정의한 파일은 클라이언트에서 가져다 쓰도록 해야한다. 아니면 클라이언트에서는 해당 인터페이스를 알 수 있는 방법이 없다. 이 인터페이스 정의 파일은 분리하면서 DLL 서버에서도 별도 파일로 분리하자.

 

내용 출처 : COM Bible

반응형

댓글