MFC의 DLL 버전을 TN033:

이 노트 Mfcxx.dll을 사용 하 여 방법과 MFCxxD.DLL (여기서 x는 MFC 버전 번호) 공유 동적 연결 라이브러리 MFC 응용 프로그램 및 확장 Dll에 설명 합니다. 일반 Dll에 대 한 자세한 내용은 다음 웹 사이트를 참조 하십시오 사용 하 여 MFC DLL의 일환으로。

이 기술 노트 Dll의 세 가지 측면을 다룹니다. 마지막 두 개의 더 많은 고급 사용자를 위한:

(이 정규 DLL 라고) 비 MFC 응용 프로그램에서 사용할 수 있는 MFC를 사용 하 여 DLL을 작성 하는 데 관심이 있다면, 기술 참고 11 참조 하십시오。

MFCxx.DLL 지원의 개요: 용어 및 파일

정규 DLL: 일반 DLL을 사용 하 여 MFC 클래스 중 일부를 사용 하 여 독립 실행형 DLL 빌드. 애플 리 케이 션/DLL 경계 인터페이스는 "C" 인터페이스와 클라이언트 응용 프로그램을 MFC 응용 프로그램 필요가 없습니다.

이 MFC 1.0에서 지원 DLL 지원의 버전입니다. 기술 참고 11 및 MFC 고급 개념 샘플에서 설명 하는 DLLTRACE。

메모nbsp;??Visual c + +의 버전 4.0, 용어 USRDLL 오래 이며 정적으로 MFC에 링크 하는 기본 DLL에 의해 대체 되었습니다. 또한 동적으로 MFC에 링크 하는 기본 DLL을 구축할 수 있습니다(&N).

MFC 3.0 (그리고 위의) 일반 Dll OLE 및 데이터베이스 클래스를 비롯 한 모든 새로운 기능 지원。

AFXDLL: 이것은 또한 라고도 MFC 라이브러리의 공유 버전. 이것은 MFC 2.0에 추가 된 새 DLL 지원 이다. MFC 라이브러리 자체는 다양 한 Dll (아래 설명 참조) 및 클라이언트 응용 프로그램 또는 DLL 필요한 Dll을 동적으로 링크 합니다. 응용 프로그램/DLL 경계 인터페이스는 C + + MFC 클래스 인터페이스. 클라이언트 응용 프로그램에는 MFC 응용 프로그램 이어야 합니다. 모든 MFC 3.0 기능 지원 (예외: 유니코드 데이터베이스 클래스에 대해 지원 되지 않습니다)。

메모nbsp;??Visual c + + 버전 4.0의이 유형의 DLL 라고 "확장 DLL."(&N)

이 노트 MFCxx.DLL 사용 하 여 MFC DLL 집합을 포함 하는 전체 참조:

메모nbsp;??MFCSxx [U] [D]입니다.LIB 라이브러리에서 사용 하는 공유 Dll에서 MFC와 함께. 이러한 라이브러리 응용 프로그램 또는 DLL에 정적으로 연결 해야 하는 코드를 포함(&N)。

해당 가져오기 라이브러리를 응용 프로그램 링크:

"MFC 확장 DLL" Mfcxx.dll을 기반으로 하는 DLL (또는 다른 MFC 공유 Dll). 여기 MFC 구성 요소 아키텍처에서 발 차기. MFC 클래스에서 파생 하는 유용한 클래스 또는 다른 MFC 같은 도구 키트를 구축 하는 경우 DLL에 배치할 수 있습니다. 궁극적인 클라이언트 응용 프로그램은 DLL로 Mfcxx.dll을 사용 한다. 이렇게 하면 재사용 가능한 리프 클래스, 재사용 가능한 기본 클래스와 문서 보기/재사용 가능한 클래스。

메모nbsp;??그것은 응용 프로그램 MFC/OLE, 데이터베이스 또는 네트워킹 클래스를 각각 사용 하지 않는 경우 MFCOxx [U] D, D [U] MFCDxx, 또는 MFCNxx [U] D 디버그 라이브러리와 링크 하는 데 필요한(&N)。

장점 및 단점

왜 MFC의 공유 버전을 사용 해야?

왜 하지 사용 해야 MFC의 공유 버전:

MFC 확장 DLL을 작성 하는 방법

MFC 확장 DLL MFC 클래스의 기능을 낸 작성 함수와 클래스를 포함 하는 DLL입니다. OLE 및 데이터베이스 디버그 지원 (MFCOxxD.DLL, MFCDxxD.DLL) Dll은 MFC 확장 Dll의 예 Mfcxxd.dll을 사용. MFC 확장 DLL 공유 MFC Dll을 사용 하 여 응용 프로그램 몇 가지 추가 고려 사항으로 그것을 사용 하 여 같은 방식으로:

이러한 고려 사항은 아래 더 자세하게에서 설명 되어 있습니다. 또한 MFC 고급 개념 샘플을 참조 해야 DLLHUSK 보여줍니다 이후

클라이언트 응용 프로그램 및 확장 Dll Mfcxx.dll의 동일한 버전을 사용 해야 합니다. MFC DLL 규칙을 따르고 모두 디버그를 제공 해야 하 고 소매 (/ 릴리스) 확장 DLL의 버전. 이렇게 하면 응용 프로그램의 디버그 버전과 일반 정품 버전을 구축 하 고 적절 한 디버그 또는 일반 정품 버전의 모든 Dll 연결을 클라이언트 프로그램。

메모nbsp;??C + + 이름 맹글링 및 내보내기 문제를 인해 확장 DLL에서에서 내보내기 목록 다른 플랫폼에 대 한 Dll과 같은 DLL의 디버그 버전과 일반 정품 버전 간에 다를 수 있습니다. 소매 Mfcxx.dll에 약 2000 내보낸 항목 포인트; 디버그 Mfcxxd.dll가 약 3000 내보낸 진입점(&N)。

메모리 관리에 대 한 빠른 참고

메모리 관리 ","이 기술 노트의 끝 근처 섹션 MFC의 공유 버전 Mfcxx.dll의 구현을 설명 합니다. 단지 확장 DLL을 구현 하는 것을 알고 하는 데 필요한 정보는 여기에서 설명。

MFCxx.DLL 및 클라이언트 응용 프로그램의 주소 공간에 로드 하는 모든 확장 Dll 같은 응용 프로그램에서 마치 동일한 메모리 할당자, 리소스 로딩 및 기타 MFC "전역" 상태 사용 됩니다. 비 MFC DLL 라이브러리와 정적으로 MFC에 링크 하는 기본 Dll 정확히 반대 하 고 있다 각 DLL 자체 메모리 풀의 할당 하기 때문에 이것은 중요 한。

확장 DLL이 메모리를 할당 하는 경우 메모리를 다른 응용 프로그램에 할당 된 개체와 함께 혼합할 자유롭게 수 있습니다. 또한, 공유 MFC 라이브러리를 사용 하는 응용 프로그램이 충돌 하는 경우 운영 체제의 보호 공유 DLL 다른 MFC 응용 프로그램의 무결성 유지 됩니다.

다른 "전역" MFC 상태에서 리소스 로드를 현재 실행 파일 처럼 클라이언트 응용 프로그램 및 모든 MFC 확장 Dll로 자체 MFCxx.DLL 간에 공유 되는 마찬가지로。

확장 DLL을 구축

Appwizard를 사용 하 여 MFC 확장 DLL 프로젝트를 만들 수 있습니다 그리고 그것은 자동으로 적절 한 컴파일러와 링커 설정을 생성 됩니다. 그것은 또한 수정할 수 하는 DllMain 함수를 생성 했다。

MFC 확장 DLL에 기존 프로젝트를 변환 하는 경우 MFC의 공유 버전을 사용 하 여 응용 프로그램을 구축 하기 위한 표준 규칙 시작 후 다음 실행:

헤더 파일 변경

확장 DLL 목적은 일반적으로 해당 기능을 사용할 수 있는 하나 이상의 응용 프로그램에 몇 가지 일반적인 기능을 내보낼입니다. 이 클래스 및 클라이언트 응용 프로그램에 사용할 수 있는 전역 함수 내보내기 귀결。

이렇게 하려면 각 멤버 함수 가져오기 또는 내보내기 적절 한 것 처럼 표시 됩니다 있는지 확인 해야 합니다. 이 특별 한 선언이 필요: __declspec (dllexport) 및 __declspec(dllimport). 클래스를 클라이언트 응용 프로그램에서 사용 하는 경우 __declspec(dllimport)으로 선언할 수 있도록 합니다. 확장 DLL 자체를 빌드할 때 __declspec (dllexport)로 선언 해야 합니다. 또한, 기능 해야 합니다 실제로 내보낼 클라이언트 프로그램 로드 시 그들에 바인딩할 수 있도록。

전체 클래스를 내보내는 AFX_EXT_CLASS 를 사용 하 여 클래스 정의에. 이 매크로 __declspec (dllexport) 으로 _AFXDLL 및 _AFXEXT 를 정의 하지만 _AFXEXT 가 정의 되지 않은 경우 __declspec(dllimport) 로 정의 하는 경우 프레임 워크에 의해 정의 됩니다. _AFXEXT 위에서 설명한 대로 정의 확장 DLL을 빌드할 때. 예를 들어:

aFX_EXT_CLASS CExampleExport 클래스: 공용 CObject
{... 클래스 정의...}

아니라 전체 클래스를 내보내는

방금 개별 필요한 클래스의 멤버를 귀하의 수출을 하는 경우도 있습니다. 예를 들어, CDialog를 내보내는-파생 클래스를만 생성자와 DoModal 호출 내보내야 할 수도 있습니다. 이러한 멤버는 DLL을 사용 하 여 내보낼 수 있습니다.DEF 파일을 하지만 당신은 또한 사용할 수 있습니다 AFX_EXT_CLASS 많이 내보내야 할 개별 구성원에 대해 동일한 방식으로。

예를 들어:

 cExampleDialog 클래스: public CDialog
{
공개:
 nbsp; AFX_EXT_CLASS CExampleDialog();
 ? AFX_EXT_CLASS int DoModal();
 ? / / 클래스 정의의 나머지
 ? .
 ? .
 ? .
}(&N)

이렇게 하면 클래스의 모든 멤버를 더 이상 내보내려는 있다는 사실 때문으로 추가 문제를 실행할 수 없습니다. 문제는 MFC 매크로 작동 방식에서 이다. 다양 한 MFC의 도우미 매크로 실제로 선언 하거나 데이터 멤버를 정의 합니다. 따라서 이러한 데이터 멤버를 DLL에서 내보낼 수 있어야 합니다.

예를 들어, DECLARE_DYNAMIC 매크로가 정의 됩니다 같이 확장 DLL을 빌드할 때:

# define DECLARE_DYNAMIC(class_name) \
보호 된: \
 nbsp; 정적 CRuntimeClass * 파스칼 _GetBaseClass(); \
 ? 공공: \
 ? 정적 AFX_DATA CRuntimeClass 클래스 # # class_name; \
 ? 가상 CRuntimeClass * GetRuntimeClass() const; \(&N)

"정적 AFX_DATA" 시작 하는 줄은 클래스 내부의 정적 개체를 선언 하 고 있다. 이 클래스를 올바르게 내보내고 클라이언트에서 런타임 정보에 액세스.EXE이 정적 개체를 수출 해야 합니다. 정적 개체는 AFX_DATA한정자로 선언 된, 때문에 하면 AFX_DATA 를 DLL을 빌드할 때 __declspec (dllexport) 을 정의 하 고 귀하의 클라이언트 실행 파일을 빌드할 때 __declspec(dllimport) 로 정의。

위에서 설명 했 듯이 AFX_EXT_CLASS 이미 이런 방식으로 정의 됩니다. 그래서 그냥 다시 AFX_DATA AFX_EXT_CLASS 와 동일 클래스 정의 주위에 필요。

예를 들어:

nbsp;??# undef AFX_DATA
 ? # define AFX_DATA를 AFX_EXT_CLASS
 ? CExampleView 클래스: 공용 CView
 ? {
 ??? DECLARE_DYNAMIC()
 ??? / /... 클래스 정의...
 ? };
 ? # undef AFX_DATA
 ? # define AFX_DATA(&N)

MFC는이 기술은 이러한 모든 시나리오에 대해 작동 하므로 해당 매크로 내에서 정의 하는 데이터 항목에 항상 AFX_DATA 기호를 사용 합니다. 예를 들어 DECLARE_MESSAGE_MAP 에 대 한 작동。

메모nbsp;??정적 데이터 멤버가 자동으로 내보내집니다 클래스의 멤버를 선택한 아니라 전체 클래스를 내보내는 경우(&N)。

DECLARE_SERIAL 및 IMPLEMENT_SERIAL 매크로 사용 하는 클래스에 대 한 CArchive 추출 연산자를 자동으로 내보내려면 동일한 기법을 사용할 수 있습니다. 클래스 선언을 괄호로 묶기 여 아카이브 연산자를 내보냅니다 (에 위치 합니다.H 파일) 다음 코드와:

# undef AFX_API
# define AFX_API AFX_EXT_CLASS

lt; 여기에 귀하의 클래스 선언을 >

# undef AFX_API
# define AFX_API

_Afxext의 제한 사항

확장 Dll의 여러 레이어를 하지 않아도 확장 Dll에 대 한 _AFXEXT pre-processor 기호를 사용할 수 있습니다. 확장 Dll 호출 또는 자신의 확장 Dll MFC 클래스에서 파생 한 다음 클래스에서 파생 하는 경우 모호성을 피하기 위해 사용자 고유의 전처리기 기호를 사용 해야 합니다.

문제는 w i n 32를 명시적으로 선언 해야 합니다 모든 데이터 __declspec (dllexport) 으로 DLL에서 가져올 수 있으면 DLL 및 __declspec(dllimport) 에서 내보낼 경우 이다. _AFXEXT를 정의할 때 MFC 헤더 AFX_EXT_CLASS 올바르게 정의 되었는지 확인。

여러 개의 레이어가 있을 때 AFX_EXT_CLASS 같은 하나의 기호 충분 하지 않습니다, 때문에 확장 DLL 수 있습니다 새 클래스를 내보낼 뿐만 될 또 다른 확장 DLL에서에서 다른 클래스를 가져올. 이 문제를 처리 하기 위해 DLL을 사용 하 여 대 DLL 자체를 구축 하는 나타내는 특별 한 pre-processor 기호를 사용 합니다. 예를 들어, 두 개의 확장 Dll, A.DLL, B.DLL 상상. 그들은 각각 A.H와 B.H, 일부 클래스를 각각 내보냅니다. B.DLL은 A.DLL에서 클래스를 사용합니다. 헤더 파일 이런식으로 생겼을 것 이다:

/ / A.H
# ifdef A_IMPL
 nbsp; # define CLASS_DECL_A __declspec (dllexport)
# else
 ? # define CLASS_DECL_A __declspec(dllimport)
# endif

CLASS_DECL_A CExampleA 클래스: 공용 CObject
{... 클래스 정의...};

/ / B.H
# ifdef B_IMPL
 ? # define CLASS_DECL_B __declspec (dllexport)
# else
 ? # define CLASS_DECL_B __declspec(dllimport)
# endif

CLASS_DECL_B CExampleB 클래스: 공용 CExampleA
{... 클래스 정의...}(&N)

/D A_IMPL와 함께 구축 하 고 A.DLL이 빌드될 때와 그것은 /D B_IMPL내장 B.DLL이 빌드될 때. 각 DLL에 대해 별도 기호를 사용 하 여 Cexampleb는 내보내고 CExampleA B.DLL을 빌드할 때 가져온. Cexamplea는 A.DLL을 빌드할 때 내보내고 가져오는 B.DLL (또는 다른 클라이언트)에서 사용 하는 경우。

내장 AFX_EXT_CLASS 와 _AFXEXT pre-processor 기호를 사용 하는 경우 이러한 유형의 레이어 링을 할 수 없습니다. 위에서 설명 하는 기술을 방식으로 안 달리 OLE, 데이터베이스 및 네트워크 확장 Dll을 빌드할 때 MFC 자체 메커니즘을 사용 하 여이 문제를 해결。

아니라 전체 클래스를 내보내는

다시 전체 클래스를 내보내는 하지 때 특별 한 주의 해야 합니다. MFC 매크로에서 만든 필요한 데이터 항목이 올바르게 내보낼 수 있도록 해야 합니다. AFX_DATA 를 특정 클래스의 매크로에 다시 여이 수행할 수 있습니다. 이 언제 든 지 전체 클래스를 내보내는 하지 이루어져야 한다。

예를 들어:

/ / A.H
# ifdef A_IMPL
 nbsp; # define CLASS_DECL_A _declspec(dllexport)
# else
 ? # define CLASS_DECL_A _declspec(dllimport)
 ? # endif

# undef AFX_DATA
# define AFX_DATA CLASS_DECL_A

CExampleA 클래스: 공용 CObject
{
 ? DECLARE_DYNAMIC()
 ? CLASS_DECL_A int SomeFunction();
 ? //class 정의 합니다.
 ? .
 ? .
};

# undef AFX_DATA
# define AFX_DATA(&N)

DllMain

다음은 확장 DLL에 대 한 기본 소스 파일에 배치 해야 하는 정확한 코드입니다. 그것은 표준 포함 후와 야 한다. 그 Appwizard를 사용 하 여 확장 DLL에 대 한 시작 파일을 만들 때 제공 DllMain 에 대 한 참고。

# include "afxdllx.h"

정적 AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
 nbsp; 경우 (dwReason DLL_PROCESS_ATTACH = =)
 ? {
 ???? / / 확장 DLL 초기화 if (!AfxInitExtensionModule (
 ??????????? extensionDLL, hInstance))
 ??????? 0; 반환

/ / TODO: 여기에 다른 초기화 작업을 수행
 ? }
 ? else if (dwReason DLL_PROCESS_DETACH = =)
 ? {
 ???? / / 확장 DLL 당 프로세스 종료
 ???? AfxTermExtensionModule(extensionDLL);

/ / TODO: 여기에 다른 정리 작업을 수행
 ? }
 ? 반환 1;?? / / 확인
}(&N)

CDynLinkLibrary 개체가 만들어질 때 AfxInitExtensionModule 을 호출 뿐만 아니라, 나중에 사용 하기 위해 해당 개체 팩터리 (COleObjectFactory 개체) 모듈 런타임 클래스 (CRuntimeClass 구조체)을 캡처합니다. (선택 사항) 호출 AfxTermExtensionModule 있게 MFC 정리 확장 DLL 각 프로세스 (어떤 프로세스가 종료 또는 DLL이 로드 FreeLibrary 호출의 결과로 발생)을 분리 하는 경우 확장 DLL에서에서. 이후 대부분의 확장 Dll을 동적으로 로드 되지 않습니다 (일반적으로, 그들은 그들의 가져오기 라이브러리를 통해 연결 된), AfxTermExtensionModule 을 호출 일반적으로 필요 하지 않습니다。

응용 프로그램 로드 하 고 동적으로 확장 Dll 해제 하는 경우 표시 above.nbsp;로 AfxTermExtensionModule 을 호출 해야 또한 응용 프로그램이 다중 스레드를 사용 하는 경우 (Win32 함수 LoadLibrary 및 FreeLibrary)는 대신 AfxLoadLibrary 및 AfxFreeLibrary 를 사용 해야 합니다. 확장 DLL 로드 하 고 언로드할 때 실행 시작 및 종료 코드가 전역 MFC 상태 손상 되지 않습니다 지키는 AfxLoadLibrary 및 AfxFreeLibrary 를 사용 하 여(&N)。

헤더 파일 AFXDLLX입니다.확장 Dll, AFX_EXTENSION_MODULE 및 CDynLinkLibrary 에 대 한 정의 등에서 사용 되는 구조에 대 한 특별 한 defintions를 포함 하는 H。

글로벌 extensionDLL 과 같이 선언 해야 합니다. 16 비트 버전의 MFC와 달리 메모리를 할당할 수 및 MFC 기능을 호출 하는이 시간 동안 MFCxx.DLL DllMain 을 호출 하는 시간에 의해 완전히 초기화 되기 때문。

리소스 및 클래스 공유

간단한 MFC 확장 Dll 클라이언트 응용 프로그램 및 아무것도 더 많은 몇 가지 낮은 대역폭 함수를 내보낼만 필요 합니다. 더 많은 사용자-인터페이스 집중 Dll 클라이언트 응용 프로그램에 리소스 및 c + + 클래스를 수출 하고자 할 수 있습니다.

리소스 내보내기는 리소스 목록을 통해 수행 됩니다. 각 응용 프로그램의 CDynLinkLibrary 개체의 단독으로 링크 된 목록이입니다. 리소스 로드 리소스 현재 리소스 모듈 (AfxGetResourceHandle)에서 첫 번째 보이는 표준 MFC 구현의 대부분을 찾고 그리고 경우 요청 된 리소스를 로드 하려고 시도 하는 CDynLinkLibrary 개체 목록 찾을 수 없습니다 도보。

C + + 클래스 이름을 지정 하는 c + + 개체의 동적 생성이 비슷합니다. MFC 개체 deserialization 메커니즘 모든 CRuntimeClass 개체를 이전에 저장 된 무슨에 따라 필요한 형식의 c + + 개체를 동적으로 만들어서 재구성할 수 있도록 등록을 할 필요가。

DECLARE_SERIAL는 확장 DLL의에서 클래스를 사용 하 여 클라이언트 응용 프로그램을 원하는 경우에 클라이언트 응용 프로그램에 표시 되도록 클래스를 내보낼 것입니다 해야 합니다. 또한 이렇게 걷고 CDynLinkLibrary 목록。

MFC 고급 개념 샘플의 경우 DLLHUSK, 목록을 다음과 같은

머리-gt; ? DLLHUSK입니다.EXE-또는-DLLHUSK입니다.EXE
 ????????????? |????????????????????? |
 ???????? TESTDLL2입니다.DLL TESTDLL2.DLL
 ????????????? |????????????????????? |
 ???????? TESTDLL1입니다.DLL TESTDLL1.DLL
 ????????????? |????????????????????? |
 ????????? MFCO42D입니다.DLL??????????????? |
 ????????????? |????????????????????? |
 ????????? MFCD42D입니다.DLL??????????????? |
 ????????????? |????????????????????? |
 ?????????? MFC42D입니다.DLL MFC42.DLL(&G)

Mfcxx.dll은 대개 리소스 및 클래스 목록의 마지막. Mfcxx.dll에는 모든 표준 명령 Id에 대 한 프롬프트 문자열을 비롯 하 여 표준 MFC 리소스의 모든 포함 됩니다. Dll과 클라이언트 응용 하지 않는 허용 목록의 꼬리에 배치는에 의존 Mfcxx.dll의 공유 리소스 대신 하지만 표준 MFC 리소스의 자체 복사본。

리소스 및 모든 Dll의 클래스 이름을 클라이언트 응용 프로그램의 네임 스페이스에 병합 단점은 어떤 Id를 조심 해야 하는 또는 이름을 선택 하고있다. 물론 하지 클라이언트 응용 프로그램에 리소스 또는 CDynLinkLibrary 개체를 내보내기 하 여이 기능을 해제할 수 있습니다. DLLHUSK 샘플 여러 헤더 파일을 사용 하 여 공유 리소스 이름 공간을 관리 합니다. 공유 리소스 파일 사용에 대 한 자세한 도움말에 대 한 기술 노트 35 참조。

DLL 초기화

위에서 설명 했 듯이 일반적으로 클라이언트 응용 프로그램을 귀하의 리소스 및 클래스를 내보낼 하려면 CDynLinkLibrary 개체를 만드는 원할 것입니다. DLL을 초기화 하는 내보낸된 진입점을 제공 해야 합니다. 최소한이 인수를 사용 하 고 아무것도 반환 void 루틴 하지만 당신 처럼 아무것도 될 수 있습니다.

이 방법을 사용 하는 경우 각 클라이언트 응용 프로그램의 DLL을 사용 하 고 싶어이 초기화 루틴을 호출 해야 합니다. 수 또한 할당이 CDynLinkLibrary 개체 DllMain 에서 AfxInitExtensionModule 을 호출 직후。

초기화 루틴의 현재 응용 프로그램의 힙, 확장 DLL 정보를 유선에서 CDynLinkLibrary 개체를 만들어야 합니다. 이 다음과 같이 할 수 있습니다.:

extern "C" extern 무효 WINAPI InitXxxDLL()
{
 nbsp; 새로운 CDynLinkLibrary(extensionDLL);
}(&N)

일상적인 이름,이 예제에서 InitXxxDLL 는 당신이 원하는 무엇이 든 될 수 있습니다. 될 필요가 없습니다 extern “C” , 하지만 하 고 그렇게 하 게 유지 하기 위해 쉽게 내보내기 목록。

메모nbsp;??귀하의 확장 일반 DLL에서 DLL을 사용 하는 경우에이 초기화 함수를 내보내야 합니다. 이 함수는 일반 DLL에서 확장 DLL 클래스 또는 리소스를 사용 하기 전에 호출 해야 합니다(&N).

항목 내보내기

클래스를 내보내는 간단한 방법을 각 클래스 및 전역 함수를 내보낼 __declspec(dllimport) 와 __declspec (dllexport)을 사용 하는 것입니다. 이것을 훨씬 더 쉽게 만든다 하지만 덜 덜 제어 기능은 무엇 얻을 내보낸 함수를 서 수로 내보낼 수 없습니다 이후 각 진입점 (아래 설명 참조)를 명명 하는 것 보다 효율적입니다. 이것은 TESTDLL1 및 TESTDLL2 자신의 항목을 내보내는 데 사용 하는 방법。

더 효율적인 방법 (Mfcxx.dll에 의해 사용 되는 방법) 이며 각 항목을 명명 하 여 각 항목을 직접 수출 하 고 있습니다.DEF 파일입니다. 이후 우리의 DLL (즉, 모든)에서 선택적 수출을 내보내는 우리가 우리가 우리가 수출 하고자 하는 특정 인터페이스를 결정 해야 합니다. 이것은 어려운 항목 형태로 맹글링된 이름을 링커에 지정 해야 합니다 이후 합니다.DEF 파일입니다. 당신이 정말로 그것에 대 한 심볼릭 링크가 필요 하지 않으면 c + + 클래스를 내보내지 마십시오。

만약 당신이 시도와 클래스 c + +를 내보내기는.DEF 파일 전에이 목록을 자동으로 생성 하는 도구를 개발 하는 것이 좋습니다. 이 할 수 있습니다 두 단계 연결 프로세스를 사용 하 여. 아니 수출으로 번 DLL에 연결 하 고 링커를 생성할 수 있도록 한.맵 파일입니다. 합니다.맵 파일 생성을 내보낸 함수 목록 일부 조작 함께 사용할 수 있습니다에 대 한 내보내기 항목을 생성 하 데 수 있습니다 귀하의.DEF 파일입니다. (비록 그것은 완전히 자동 튜닝 동안에 한 번씩 몇 가지 손이 필요) 같은 프로세스와 함께 MFCxx.DLL 및 OLE, 수천, 번호에서 데이터베이스 확장 Dll에 대 한 내보내기 목록 생성。

CWinApp 대 CDynLinkLibrary

MFC 확장 DLL은 CWinApp있지 않습니다-파생 된 개체는 자신의; 대신 CWinApp와 함께 작업을 해야 합니다-클라이언트 응용 프로그램의 개체를 파생 합니다. 즉, 클라이언트 응용 프로그램에 기본 메시지 펌프, 유휴 루프를 소유。

MFC 확장 DLL이 각 응용 프로그램에 대 한 추가 데이터를 유지 하는 경우에 CDynLinkLibrary 에서 새 클래스를 파생 하 고 위의 루틴을 설명 하는 Initxxxdll에 만들 수 있습니다. 실행 하는 경우 DLL의 CDynLinkLibrary 개체는 특정 확장 DLL에 대 한 하나를 찾아 현재 응용 프로그램의 목록을 확인할 수 있습니다.

DLL 구현에서 리소스를 사용 하 여

위에서 설명 했 듯이 기본 리소스 부하 최초의 EXE 또는 DLL는 요청한 리소스에 대 한 찾고 CDynLinkLibrary 개체 목록을 걸어 나갈 것 이다. 모든 내부 코드 뿐만 아니라 모든 MFC Api AfxFindResourceHandle 를 사용 하 여 도보 있을 수 있습니다 아무리 어떤 리소스를 찾을 수 자원 목록。

Api를 사용 하는 경우에 특정 장소에서 리소스를 로드 하려면 AfxGetResourceHandle 및 AfxSetResourceHandle 이전 핸들을 저장 하 고 새로운 핸들을 설정 합니다. 클라이언트 응용 프로그램에 반환 하기 전에 오래 된 리소스 핸들을 복원 해야 합니다. 샘플 testdll2이이 접근을 사용 하 여 명시적으로 로드 하는 메뉴에 대 한。

목록 산책 약간 느립니다 및 리소스 ID 범위를 관리 해야 하는 단점이 있다. 여러 확장 Dll에 연결 하는 클라이언트 응용 프로그램 DLL 인스턴스 핸들을 지정 하지 않고도 DLL에서 제공한 리소스를 사용할 수 있는 장점이 있다. AfxFindResourceHandle 자원 목록을 산책 일치 하는 특정된 항목에 대 한 보고 하는 데 사용 하는 API입니다. 이름 및 리소스의 유형을 소요 되 고 처음 발견 된 리소스 핸들 (또는 NULL)을 반환 합니다.

DLL 버전을 사용 하 여 응용 프로그램 작성

응용 프로그램 요구 사항

MFC의 공유 버전을 사용 하는 응용 프로그램 몇 가지 간단한 규칙을 따라야 합니다.:

개발 환경 구축

대부분 표준 기본값의 내부 메이크파일 사용 하는 경우 DLL 버전을 구축 하는 프로젝트를 쉽게 변경할 수 있습니다.

다음 단계는 NAFXCWD와 연결 되어 올바르게 작동 MFC 응용 프로그램을 가정 합니다.(디버그)에 대 한 LIB 및 NAFXCW입니다.LIB (소매)에 대 한 하려면 MFC 라이브러리의 공유 버전을 사용 하도록 변환 합니다. Visual c + + 환경에서 실행 하 고 있고 내부 프로젝트 파일。

  1. 빌드 메뉴에서 설정을 선택 합니다. 프로젝트 설정 아래의 일반 페이지에서 설정 Microsoft Foundation Classes (MFCxx(d).dll) 공유 DLL에서 MFC 사용。

NMAKE 빌딩

Visual c + +의 외부 메이크파일을 기능을 사용 하는 또는 직접 NMAKE 사용 하는 경우에 컴파일러 및 링커 옵션을 지원 하도록 메이크파일 편집 해야

필요한 컴파일러 플래그:

/ /MD D_AFXDLL

/ D_AFXDLL

표준 MFC 헤더 필요이 기호를 정의할 수:

/MD

응용 프로그램에서 C 런타임 라이브러리의 DLL 버전을 사용 해야 합니다.

다른 모든 컴파일러 플래그에 따라 MFC 기본값 (예를 들어, _DEBUG 디버그에 대 한)。

라이브러리 링커 목록을 편집 합니다. NAFXCWD 변경 합니다.MFCxxD.LIB LIB 및 NAFXCW 변경 합니다.LIB를 MFCxx.LIB. MFCOxx[U]D.LIB, MFCDxx[U]D.LIB, 및 MFCNxx[U]D.LIB 적절 하 게 추가 (MFC/OLE, 데이터베이스 또는 네트워킹 클래스의 사용을 위한 필수). LIBC를 교체 합니다.MSVCRT와 LIB.LIB입니다. 다른 MFC 라이브러리와 함께 그것이 중요 MFCxxD.LIB 전에 배치 됩니다 C-런타임 라이브러리。

모두 당신의 소매에 /d_afxdll을 추가 하 고 디버그 리소스 컴파일러 옵션 (하나 실제로 /r와 리소스를 컴파일하는) 수도 있습니다. 이것은 최종 실행 파일을 MFC Dll에 존재 하는 리소스를 공유 하 여 작은。

후에 이러한 변경 내용이 전체 다시 빌드는 필요。

샘플 빌드

명령줄에서 공유 호환 NMAKE 메이크파일 또는 Visual c + +에서 MFC 샘플 프로그램의 대부분을 건설 될 수 있다。

Mfcxx.dll을 사용 하 여 이러한 샘플을 변환 하려면 로드할 수 합니다.MAK는 Visual c + +로 파일 및 위에서 설명한 프로젝트 옵션을 설정 합니다. NMAKE 빌드를 사용 하는 경우 지정할 수 있습니다 "AFXDLL = 1"에 NMAKE 명령줄 및 구축 예정 공유 MFC 라이브러리를 사용 하 여 샘플。

MFC 고급 개념 샘플 DLLHUSK MFC의 DLL 버전을 내장. 이 샘플은 뿐만 아니라 MFCxx.DLL로 연결 된 응용 프로그램을 구축 하는 방법을 보여 줍니다. 있지만 그것은 또한이 기술 노트의 뒷부분에서 설명 하는 MFC 확장 Dll과 같은 MFC DLL 패키징 옵션의 다른 기능을 보여 줍니다.

포장 노트

([U] MFCxx Dll의 일반 정품 버전.DLL)은 자유롭게 재배포 가능 합니다. Dll의 디버그 버전은 자유롭게 재배포 가능 하 고 응용 프로그램 개발 동안에 사용 해야 한다。

디버그 Dll 디버깅 정보가 제공 됩니다. Visual c + + 디버거를 사용 하 여 DLL 응용 프로그램의 실행을 추적할 수 있습니다. 릴리스 Dll (MFCxx [U].DLL) 디버깅 정보를 포함 하지 않는。

사용자 지정 또는 Dll을 다시 작성 하는 경우 다음 호출 해야 그들이 뭔가 "MFCxx" The MFC SRC 파일 MFCDLL 아닌 다른.MAK 빌드 옵션을 설명 하 고 DLL의 이름을 변경 하는 논리를 포함 합니다. 이 규칙은 MFC/OLE, 데이터베이스 및 네트워크 MFCOLE에 의해 만들어진 하는 Dll에도 적용 됩니다.MAK, MFCDB입니다.MAK, 그리고 MFCNET입니다.MAK, 각각. 이후 이러한 Dll은 잠재적으로 많은 MFC 응용 프로그램에서 공유 파일의 이름을 변경 하는 것은 필요입니다. 사용자 지정 버전의 MFC Dll을 갖는 대체 그 시스템에 설치 되어 공유 MFC Dll을 사용 하는 다른 MFC 응용 프로그램 중단 될 수 있습니다.

MFC Dll을 다시 권장 되지 않습니다.

MFCxx.DLL 구현 방법

다음 단원에서는 MFC DLL (MFCxx.DLL 및 MFCxxD.DLL) 구현 하는 방법을 설명 합니다. 여기에 세부 사항이 이해 할 모든 중요은 MFC DLL을 사용 하 여 응용 프로그램입니다. 여기에 내용을 MFC 확장 DLL을 작성 하는 방법을 이해 하는 데 필수적입니다. 하지만,이 구현 이해 자신의 DLL을 작성 하는 데 도움이 될 수 있습니다.

구현 개요

위에서 설명한 대로 MFC DLL은 MFC 확장 DLL의 특별 한 경우 정말. 그것은 매우 많은 많은 클래스에 대 한 수출. 가지 몇 가지 추가 MFC DLL에서 정규 확장 DLL 보다 더욱 특별 하 게。

Win32는 대부분의 작업

16 비트 버전의 MFC 응용 프로그램 당 데이터 스택 세그먼트에 일부 80 x 86 어셈블리 코드, 프로세스 당 예외 컨텍스트 및 기타 기술에 의해 만들어진 특별 한 세그먼트를 포함 한 특별 한 기술 수가 필요 합니다. Win32 직접 지원 프로세스 당 데이터 DLL에는 당신이 원하는 대부분의 시간. 가장 부분에 대 한 MFCxx.DLL 단지 NAFXCW입니다.LIB는 DLL에 패키지 합니다. MFC 소스 코드를 보면 될 필요가 매우 몇 가지 특별 한 경우 이기 _AFXDLL, # ifdef 매우 몇 가지를 찾을 거 야. Win32 Windows 3.1 (Win32s 라고도 함)를 해결 하는 구체적으로 하는 특별 한 경우. Win32s MFC DLL 스레드 로컬 저장소 (TLS) 프로세스 로컬 데이터를 얻기 위해 Win32 Api 사용 해야 합니다 그래서 직접 지원 프로세스 당 DLL 데이터를 하지 않습니다.

라이브러리 소스, 추가 파일에 대 한 영향

일반 MFC 클래스 라이브러리 소스 및 헤더에서 _AFXDLL 버전의 영향을 상대적으로 사소한입니다. 거기에 특별 한 버전 파일 (AFXV_DLL.H) 뿐만 아니라 추가 헤더 파일 (AFXDLL_.H) 주요 AFXWIN 포함 되어 있습니다.H 헤더입니다. AFXDLL_입니다.H 헤더에는 CDynLinkLibrary 클래스 및 기타 구현 세부 _AFXDLL 응용 프로그램 및 MFC 확장 Dll의 포함 됩니다. AFXDLLX입니다.MFC 확장 Dll (자세한 내용은 위의 참조) 구축을 위한 H 헤더를 제공 하는。

MFC SRC에서 MFC 라이브러리를 정규 소스 _AFXDLL # ifdef 아래 추가 조건부 코드 몇 가지 있다. 추가 소스 파일 (DLLINIT.CPP) 추가 DLL 초기화 코드 및 MFC의 공유 버전을 위해 다른 접착제를 포함합니다.

MFC의 공유 버전을 구축 하기 위해서는 추가 파일이 제공 됩니다. (아래 참조 DLL을 작성 하는 방법에 대 한 자세한 내용은.)

MFC DLL 빌드

MFC DLL은 의도적으로 어려운, 그래서 두 번 생각 재건 (또는 3 번) 그것을 하기 전에. MFC DLL을 다시 작성 해야, 당신은 만약 당신이 이해 잠재력 포장 문제 및 아래에서 설명 하는 재배포 제한 여전히 정말。

MFCDLL입니다.MAK 파일 CodeView 정보와 디버그 DLL을 구축할 예정 이다:

NMAKE /f mfcdll.mak DEBUG = 1 LIBNAME MYMFC =

MFCDLL입니다.MAK 파일 CodeView 정보 없이 릴리스 DLL을 구축할 예정 이다:

NMAKE /f mfcdll.mak DEBUG = 0 LIBNAME MYMFC =

(마찬가지로, 당신은 MFCOLE 사용합니다.MAK, MFCDB입니다.MAK, 그리고 MFCNET입니다.MAK MFCOxxD.DLL, MFCDxxD.DLL 및 MFCNxxD.DLL-MFC/OLE, 데이터베이스 및 네트워크 클래스를 포함 하는 Dll 빌드)

이 표준 MFCxx.DLL 및 MFCxxD.DLL 이름 가진 MFC SRC 디렉터리에서 MFC DLL의 개인 버전을 구축할 예정 이다. 새 Dll을 사용 하 여 경로에 적절 한 위치에 복사 해야 합니다. MFCDLL입니다.MAK 메이크파일 또한 가져오기 라이브러리 (MFCxx.LIB 및 MFCxxD.LIB)를 다시 작성 하 고 표준 MFC LIB 디렉터리에 배치 합니다. 이 그래서 미리 MFCxx.LIB 및 MFCxxD.LIB 라이브러리를 대체 하는 게 됩니다 조심 하십시오。

수정된 버전의 MFC DLL 라이브러리를 재배포 하고자 하는 경우는 MFCDLL에 있는 DLL의 이름을 변경 해야 합니다.MAK 메이크파일 및 두입니다.DEF 파일입니다. 메이크파일 MFCDLL를 참조 하십시오.MAK에 대 한 자세한 정보。

라이브러리를 수정 하 고는 소매를 재배포할 수 있습니다 (/ 릴리스) MFCxx.DLL 이외의 다른 이름을 변경 하는 경우에 수정 라이브러리. 내장 또는 사용자 지정 구축된 디버그 DLL의 디버그 버전 재배포 하지 않을 수 있습니다.

이러한 재배포 제한은 주로 비표준의 확산을 방지 하는 잠재적으로 바이러스를 포함 하는 Dll. 이상적으로 당신이 필요가 없습니다 Dll을 다시 작성 하 고 자신과 귀하의 사용자에 대 한 많은 문제를 피할 것 이다 미리 MFCxx.DLL Visual c + + 제품과 함께 제공 된 응용 프로그램을 재배포 하는 경우。

메모리 관리

Mfcxx.dll을 사용 하 여 응용 프로그램 MSVCRTxx.DLL, 공유 C 런타임 DLL에서 제공 하는 일반적인 메모리 할당자를 사용 합니다. 모두 응용 프로그램, 모든 확장 Dll로 스스로 MFC Dll이 공유 메모리 할당자를 사용합니다. 사용 하 여 메모리 할당에 대 한 공유 DLL, MFC Dll 응용 프로그램 또는 반대로 해제 나중에 메모리를 할당할 수 있습니다. 응용 프로그램과 DLL 같은 할당자를 사용 해야 하기 때문에 c + + 전역 new 연산자 또는 연산자 삭제하지 재정의 해야 합니다. 동일한 규칙 (malloc, realloc, 무료, 등등.)와 같은 C 런타임 메모리 할당 루틴의 나머지 부분에 적용。

DLL 이름, 서 수 및 클래스 __declspec (dllexport)

우리는 사용 하지 않습니다를 class c + + 컴파일러의 __declspec (dllexport) 기능. 대신, 수출의 목록 (MFCxx.DEF 및 MFCxxD.DEF) 클래스 라이브러리 소스와 함께 포함 됩니다. 이러한 진입점 (함수 및 데이터)의 집합은 선택 내보내집니다. MFC 개인 구현 함수 또는 클래스와 같은 다른 기호를 내보내지 않습니다 모든 수출 서 거주 또는 비-상주 이름 테이블의 문자열 이름 없이 의해 수행 됩니다 。

사용 하 여 class __declspec (dllexport) 작은 Dll을 구축 하기 위한 대안 될 수 있습니다 하지만 MFC와 같은 큰 DLL의 경우 기본 내보내기 메커니즘 효율성과 용량 제한 。

이 모든 수단 이란 우리가 많은 양의 약 800 (kbyte 단위) 많은 실행 타협 없이 로딩 속도은 MFCxx.DLL 릴리스에서 기능을 포장할 수 있다. MFCxx.DLL 됐을 100 K 큰이 기법이 되지 사용 합니다.또한 이렇게 그것의 끝에 추가 엔트리 포인트를 추가할 수는 있습니다.DEF 파일을 서 수로 내보내기의 속도 및 크기 효율성을 타협 하지 않고 단순 버전 관리를 허용 합니다. MFC 클래스 라이브러리에서 주 버전 개정 라이브러리 이름이 변경 됩니다. 즉, MFC30.DLL에는 MFC 클래스 라이브러리의 버전 3.0을 포함 하는 재배포 가능 DLL입니다. 이 DLL의 업그레이드 말, 가상 MFC 3.1 DLL MFC31 라는 것 이다.DLL 대신. 다시 말하지만, MFC DLL의 사용자 정의 버전을 생산 하는 MFC 소스 코드를 수정 하는 경우 사용 하십시오 다른 이름 (및 선호 하나 "MFC" 없이) 이름。

기술 노트 번호로 |nbsp; 카테고리별 기술 노트(&N)

Index