Dynamic Link Library (DLL) > MFC Tip

본문 바로가기
사이트 내 전체검색

MFC Tip

Dynamic Link Library (DLL)

페이지 정보

profile_image
작성자 이즈
댓글 0건 조회 1,108회 작성일 06-12-27 00:22

본문

1. DLL이란?

 DLL은 서로 다른 프로그램이 하나의 파일을 공유할 목적으로, 1983년 Microsoft의 연구원 John Macley에 의해 설계되었습니다. DLL은 프로그램 실행시 연결되는 라이브러리로 함수와 리소스로 구성된 이진(Binary)파일이죠. 우리가 사용하는 FileOpen 다이얼로그나 Font 다이얼로그 같은 공통 다이얼로그도 commdlg.dll 파일에 정의되어 있으며 대부분의 응용 프로그램이 공유하면서 사용합니다.

 만약에 이러한 기능을 각각의 프로그램에서 따로 구현한다면 코드와 리소스의 중복으로 메모리 낭비를 초래할 겁니다. 따라서 일반화시킬 수 있는 공통적인 기능을 DLL로 구현한다면 코드의 재사용성을 높이고, 리소스의 소모를 줄일 수도 있게 됩니다.

 

2. DLL을 만들어낸 목적

 일반사용자가 사용하는 하드디스크와 메모리는 몇년 전에 비해 배로 증가했지만 여전히 모자랍니다. 그 이유는 프로그램이 버전업 될 때마다 사용자 구미에 맞는 기능을 추가하다 보니 실행 파일의 증대는 물론 많은 양의 리소스를 요구하기 때문이지요. 이와 같이 점점 비대해지는 실행파일의 크기나 리소스의 문제를 해결하기 위한 대안이 바로 DLL입니다.

 

3. DLL의 장점

1) 한 코드를 여러 프로그램이 동시에 사용하기 때문에 메모리가 절약됩니다. 정적으로 링크된 라이브러리의 경우 각 프로그램마다 라이브러리 코드를 별도로 가지고 있기 때문에 이중 삼중으로 메모리를 낭비하게 됩니다. DLL을 사용하는 프로그램은 자신의 고유 코드만 가지고 있으며 DLL은 딱 한번만 읽어와 여러 프로그램이 공유하므로 메모리 절약 효과가 큽니다.

2) DLL을 사용하는 프로그램은 크기가 작습니다. 정적 링크를 사용하는 경우 실행파일에 라이브러리가 모두 포함되므로 실행파일이 커지게 됩니다. 프로그램이 커진다는 것은 여러 가지 문제를 야기시키는데 일단은 하드디스크의 용량을 많이 소모하게 되고 프로그램을 읽어오는 속도도 느려지게 됩니다. DLL은 프로그램의 크기도 작을 뿐만 아니라 한번 메모리에 읽어온 DLL은 다시 읽지 않고 실행파일만 읽어오기 때문에 로딩속도도 빠릅니다.

3) DLL을 교체하여 프로그램의 성능을 향상시키기 쉽습니다. DLL과 이 DLL을 사용하는 클라이언트 프로그램은 논리적으로 연결되기는 하지만 독립적인 프로그램이므로 클라이언트 프로그램은 그대로 사용하고 DLL만 교체해 주면 프로그램의 성능도 같이 향상되는 결과를 가져오게 됩니다.

4) 리소스의 교체가 가능합니다. DLL에는 함수뿐만 아니라 리소스가 같이 포함될 수 있는데, 상황에 따라 사용해야 하는 리소스가 다르다면 이 리소스를 DLL로 분리해 두고, 그때 그때 상황에 따라 다른 DLL을 읽어와 사용할 수 있죠. 다국어 버전을 지원하는 프로그램이 그 좋은 예가 됩니다. 언어뿐만 아니라 색상이나 화면 해상도에 따라 가장 적절한 리소스를 사용하도록 하고 싶을 때도 DLL을 사용할 수 있습니다.

5) 디버깅이 용이해집니다. 실행파일에 포함되는 코드의 양이 적어지므로 당연히 말썽이 되는 코드의 양도 적어지고 버그가 숨어있는 범위가 좁아지므로 디버깅을 효율적으로 할 수 있는 것은 당연합니다. 이러한 장점은 사용하는 DLL에 버그가 없다는 확신이 있을 때 뿐이며, 만약 DLL에 버그가 있다면 이때는 정말 잡기 힘든, 때로는 수정 불가능한 버그가 되는 단점이 되기도 합니다.

6) 혼합 프로그래밍이 가능해집니다. 물론 여러 가지 언어를 사용하여 프로그램을 개발하는 것은 DLL이 아니라도 가능하지만 DLL을 사용하면 어떤 개발 툴과도 접속할 수 있습니다.

7) 프로그램이 모듈화됩니다. 큰 프로그램을 개발할 때 DLL을 사용하면 프로그램이 DLL단위로 모듈화되기 때문에 각각을 독립적으로 개발할 수 있습니다. 따라서 애플리케이션의 특정부분이 업그레이드 되었을 때는 해당부분에 대한 DLL파일만 새로 설치하면 되죠.

 

4. 메인 프로그램과 DLL파일의 연결

 메인 프로그램에서 DLL 파일을 불러오는 방법에는 명시적 방법(Explicit Linkage)과 암시적 방법(Implicit Linkage)의 두 가지가 있습니다.

4.1 암시적 방법(Implicit Linkage)

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

DLL 안에는 DLL에 포함되어 있는 모듈들이 기록되어 있습니다. 실질적으로 Text 에디터를 이용하여 DLL을 열어 보면 다음과 같은 형태의 글자가 있습니다.

0CMyDib@@QAE@PAD@Z ??1CMyDib@@UAE@XZ ??_7CMyDib@@6B@

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

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

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

이렇게 물어보는 사람도 있을 것입니다. 이유는 메인프로그램을 컴파일하고 링크할 때 DLL 안에 있는 함수들은 메인프로그램에는 어느 것과도 링크되어 있지 않아 실행 파일로 만들 때 에러가 나오기 때문입니다. 예를 들어, PaintImage(LPSTR  filename);이라는 함수를 DLL로 만들어 놓고 메인프로그램에서 헤더에 extern "C"__declspec(dllimport)void PaintImage(LPSTR filename);이라고 정의하면 컴파일은 하지만 링크할 때 PaintImage 함수를 찾을 수 없다고 하며 에러를 리턴하고 실행 파일을 만들 수 없게 됩니다. 따라서, PaintImage라는 함수를 가상으로 만들어 그것을 0으로 설정해 주는 하나의 함수가 있어야 합니다.

void PaintImage(LPSTR  fileanem)=0;

이렇게 만들어진 함수가 컴파일되어 LIB로 만들어집니다. 따라서, 메인프로그램에서는 실행 내용이 아무것도 들어 있지 않은 LIB를 프로젝트에 삽입하고 컴파일하는 것이죠. 그런 후 프로그램이 실행되면 LIB에 설정된 파일명에 따라 DLL을 로드하고 프로그램 메모리 안에 DLL에서 로드시킨 PaintImage 모듈을 삽입시키게 됩니다. 결국 우리는 DLL을 만들고 난 후 3가지의 파일을 이용해서 메인프로그램을 제작하게 되는 것입니다. 이 3가지 파일은 다음과 같습니다.

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

 다음은 암시적 방법의 장단점입니다.

 1) DLL이 메모리에 로드되는 시점 - 프로그램이 실행되면 DLL도 함께 로드

 2) DLL이 메모리에서 해제되는 시점 - 프로그램이 종료되면 DLL도 해제

 3) 익스포트 함수 사용 시점 - 프로그램이 실행되는 동안 어디서나

 4) 장점 - 함수 호출이 간편

 5) 단점 - 프로그램이 실행되는 동안 DLL이 계속적으로 존재하기 때문에 메모리 낭비가 발생하고, DLL 로딩 실패시 프로그램 자체가 실행되지 않는 문제점이 있다.

 

4.2 명시적 방법(Explicit Linkage)

명시적 방법의 장단점은 다음과 같습니다.

 1) DLL이 메모리에 로드되는 시점 - LoadLibrary() 함수 호출시

 2) DLL이 메모리에서 해제되는 시점 - FreeLibrary() 함수 호출시

 3) 익스포트 함수 사용 시점 - GetProcAddress() 함수 호출시

 4) 장점 - DLL이 필요할 때마다 로드할 수 있어 메모리 소모가 적고, DLL 로딩이 실패하더라도 대응 코드를 만들 수 있다.

 5) 단점 - 함수 호출이 다소 복잡

 

5. MFC DLL 파일들의 명명 규칙

 MFC에 포함된 DLL 파일들은 사용목적에 따라 일정한 규칙을 가지고 이름이 지어졌는데, 공유 MFC DLL 파일들의 이름 형식은 다음과 같습니다.


    명명형식 : M F C [ O | D | N ] x 0 [ U ] [ D ] . D L L

 모두 MFC로 시작하며 '[ ]' 사이의 문자는 사용될 수도 있고 사용되지 않을 수도 있습니다. 또 ' | '로 구분된 문자들은 그 중 한가지가 사용될 수 있음을 뜻합니다. 'O'는 ActiveX, 'D'는 디버그용, 'N'은 네트웍과 관련됨을 의미합니다. 그리고 'x'는 버전을 의미하죠.

이런 규칙을 염두에 두고 다음을 봅시다.

MFCx0.DLL
 안시(ANSI) 릴리즈 버전(Release Version)
 
MFCx0U.DLL
 유니코드(Unicode) 릴리즈 버전
 
MFCx0D.DLL
 안시 디버그 버전(Debug Version)
 
MFCx0UD.DLL
 유니코드 디버그 버전
 
MFCOx0D.DLL
 ActiveX, 안시 디버그 버전
 
MFCOx0UD.DLL
 ActiveX, 유니코드 디버그 버전
 
MFCDx0D.DLL
 데이터베이스, 안시 디버그 버전
 
MFCDx0UD.DLL
 데이터베이스, 유니코드 디버그 버전
 
MFCNx0D.DLL
 네트웍 (소켓), 안시 디버그 버전
 
MFCNx0UD.DLL
 네트웍 (소켓), 유니코드 디버그 버전
 
 
 
 
MFCSx0.LIB
 정적링크된 코드, 릴리즈 버전
 
MFCSx0D.LIB
 정적링크된 코드, 디버그 버전
 

* 버전 번호는 아마 30, 32, 40, 42... 식으로 다른 형태를 갖고 있을 것이다.
* ActiveX, 데이터베이스, 네트웍 관련 DLL의 경우 릴리즈 버전이 없다는 것을 주목하라. 릴리즈 버전의 라이브러리는 모두 MFCx0.DLL에 포함된다.
* LIB 확장자를 갖는 파일은 임포트 라이브러리로써 응용 프로그램이나 확장 DLL을 만들때 사용되지만 다른 DLL 파일들과 같은 명명형식을 취한다.

이왕 설명한 김에 정적 링크 라이브러리 (*.LIB)도 소개 하겠습니다. 이것들의 명명규칙은 동적링크 라이브러와는 조금 다릅니다.

명명형식 : [ N | U ] A F X C W [ D ] . L I B

NAFXCW.LIB
 릴리즈 버전
 
NAFXCWD.LIB
 디버그 버전
 
UAFXCW.LIB
 릴리즈 버전 (유니코드)
 
UAFXCWD.LIB
 디버그 버전 (유니코드)
 

 

기타 다음과 같은 기본 파일이 있습니다.

MSVCRT.DLL C
 런타임 라이브러리
 
CTL3d32.DLL
 3D 콘트롤
 

 

6. 응용 프로그램과 함께 제공해야 하는 MFC DLL

 MS VC++로 작성된 응용 프로그램은 생성방법에 따라 몇 개의 동적 링크 라이브러리(DLL)의 지원을 필요로 합니다. 응용 프로그램 뿐만 아니라 확장 DLL도 마찬가지죠.

 MFC DLL을 마음대로 배포할 수 있는 권리는 마이크로소프트로부터 VC++을 정식으로 구입함과 동시에 얻어집니다. 결국 프로그래머는 2차적으로 MFC DLL을 배포하게 되는 것이며 따라서 재배포라는 표현을 쓰게 됩니다.

 응용 프로그램이 동적 링크 라이브러리를 사용한다고 해서 모든 MFC DLL 파일들을 제공해야 하는 것은 아닙니다. 앞서 보았듯이 각각의 기능이 틀리므로 응용 프로그램이나 확장 DLL에서 사용한 라이브러리만을 제공하면 됩니다. 이제 좀 더 자세히 알아보죠.

 

6.1 어떤 경우라도 포함시켜야 하는 라이브러리

 최소한 MFCx0.DLL과 MSVCRT.DLL이 필요합니다. MFCx0.DLL은 모든 기본 프레임워크 클래스를 포함하기 때문이죠. 유니코드를 지원한다면 MFCx0U.DLL로 대신합니다.

 MSVCRT.DLL은 C 런타임 라이브러리를 담고 있습니다. 내가 만든 응용 프로그램에선 C 런타임 라이브러리의 함수를 결코 사용하지 않았는데도 꼭 필요할까요? 그렇습니다. 여러분의 응용 프로그램이 직접 사용하진 않더라도 모든 MFC DLL 들이 C 런타임 라이브러리 공유 버전을 사용하므로 결국 MSVCRT.DLL 이 팔요합니다.

 또 3D 콘트롤을 지원한다면 CTL3d32.DLL 파일을 넣어 주어야 합니다. 만약 win32s ( window 3.1 플랫폼에서 돌아가는 16bit 응용 프로그램 ) 의 경우엔 win32s용 CTL3d32.DLL을 제공해야 합니다.

 

6.2 MFC 데이터베이스 클래스를 사용한 경우

 CRecordset 또는 CRecordView 와 같은 데이터베이스 클래스를 사용했다면 ODBC와 ODBC 드라이버를 재배포해야 합니다. ODBC 파일 목록은 ODBC 설치파일과 함께 온라인 도움말에 나와있습니다.

 

7. 재배포시 주의점

7.1 만약 응용 프로그램을 자동으로 설치해 주는 설치프로그램이 준비되어 있다면 윈도우즈 시스템 디렉토리에 복사해 넣기 전에 이전 버전을 확인해야 합니다. 당연한 얘기겠지만 더 오래전 만든 MFC DLL 파일을 최근의 것으로 덮어쓰는 것은 문제가 없지만 그 반대일 경우 문제가 됩니다. 이미 그것을 사용하고 있던 다른 응용 프로그램도 생각해야 하기 때문입니다.

7.2 앞서 표에서 보았듯이 MFC DLL 들은 릴리즈 버전과 디버그 버전이 따로 있습니다. 재배포할 경우엔 반드시 릴리즈 버전을 선택해야 합니다. 정확한 이유는 모르겠지만 온라인 도움말이 그렇게 지시하고 있습니다. 이것과 관련하여 주의할 점은 ActiveX나 데이터베이스 그리고 네트웍을 지원하는 라이브러리는 디버그 버전일 경우 여러개의 DLL에 나뉘어 있지만 릴리즈 버전에선 하나의 DLL에 함께 들어있다는 것입니다.

7.3 재배포가 가능한 모든 파일들은 VC++ CD의 REDIST 폴더에 담겨있으므로 만들어진 응용 프로그램과 함께 이것들을 복사하여 배포하면 됩니다.
이것들은 VC++ 설치시 하드디스크에 옮겨지지 않지만 설치옵션에 따라 몇몇 파일들은 윈도우즈의 시스템 디렉토리에 복사됩니다. 그렇더라도 재배포용으로는 CD에 있는 파일들을 사용해야 합니다. 이유는 다른 응용 프로그램에 의해 변경될 가능성이 있기 때문이겠죠.

7.4 CTL3d32.DLL의 경우 win32s 용이라면 ANSI 디렉토리에 있는 것을 사용해야 합니다.

댓글목록

등록된 댓글이 없습니다.

Total 172건 5 페이지

검색

회원로그인

회원가입

사이트 정보

컴퓨터 정보,윈도우즈,리눅스,포토샵,3ds
맥스,프로그래밍 강좌팁

접속자집계

오늘
447
어제
359
최대
5,287
전체
636,153
Copyright © www.qdata.co.kr All rights reserved.