페이지

글타래

2009년 6월 15일 월요일

MFC 확장 DLL,정적 라이브러리로 링크는 안되는 것일까? -- 정답:안된다

환경 : Windows XP
Visual Studio 2008 SP1, 한글
일반적으로 바이너리에 정적 라이브러리를 포함하기 위해서는 아래 그림과 같이 프로젝트 속성 페이지에서
"구성속성 - 일반 - MFC 사용"을 정적 라이브러리에서 MFC 사용으로 변경하면 된다.

하지만, DLL의 경우 "fatal error C1189: #error : Please use the /MD switch for _AFXDLL builds" 이런 에러 메세지를 만나게 될것이다.
이럴때는 아래의 두개의 이미지에 보이는대로 "전처리기 - 전처리기 정의"에 _AFXDLL를 추가하고 "코드 생성 - 런타임 라이브러리"를 다중 스레드 디버그 DLL(/MDd)로 변경하면된다.
* 릴리즈 모드일때는 다중 스레드 DLL(/MD)로 변경하면 되겠죠.


------------------------------------------------------------------------------------------------
위(↑) 라고 되어있는 부분에 대해 사견을 펼칩니다.
물론 맞는 말입니다만,

근데 이렇게 하면 빌드는 에러없이 되도 나중에 Dependency 로 보면 그 DLL이 MFC에 정적으로 빌드된게 아니란걸 알게될겁니다.즉,MFCxx.dll 들이 물려있습니다.예를 들어 , MFC 클래스중 CDialog 를 파생한 나만의 CMyDialog를 DLL에 구현하고 EXE 측에서 이를 오버라이드한 CAboutDlg를 생성한후 런하면 바로 죽습니다.

(MFC클래스를 안쓰면 잘돌겠지만,,,API만 쓴다면 표준 라이브러리 DLL 과 구분지을 필요도 없고..목적은 MFC를 쓰려는건데..)즉,만들었지만 MFC함수나 클래스를 쓰지도 못하는 빈껍데기의 무용지물의 정적 dll이되고 마는거죠..

이 MFC 를 정적으로 링크한 DLL을 만들려면 위옵션과 반대로 /MT 에다가 _AFXDLL은 없어야 하며, 정적라이브러리에서 MFC사용으로 해야 합니다..

단지,이것 EXE와 AFX_MANAGE_STATE 관련해서 오류가 난다는것..오류가 없으려면 DLL내에서 만든 클래스는 오직 DLL내에서만 사용하고 소멸되어져야 하거나, 아니면 AfxGetApp()나 MFC내부적으로 쓰는 위의 AFX_MANAGE_STATE 관련 코드를 타지않도록 피해가야 한다는것입니다.결국 MFC에 문제가 많다는 결론입니다.

MFC의 많은 DLL을 설치배포시 포함안하려고 정적링크를 택해서 EXE만들고, 그에 딸린 나만의 DLL 식구들도 정적으로 링크해서 빌드하려했는데,위의 쓰레드나 메시지 처리등에서 치명적인 오류로 걸리는 군요...
VC++의 DLLHusk 와 DllScreenCap 샘플 프로젝트로 테스트 해보시면 됩니다.
CResizeDialog를 dll에 선언한후 Export 하고, EXE의 CAboutDlg를 CDialog 대신 CResizeDialog로부터 오버라이드 하면 됩니다. 아마도 OnNTColor() 이벤트에서 AFX_MANAGE_STATE 관련하여 ,또는 CThreadSlotData 에 ASSERT(nSlot != 0 && nSlot < color="#3333ff">OO 개의 댓글을 누르면 됩니다.


MFC 확장 Extension DLL _declspec(dllexport) 사용하는 방법

확장 DLL
http://msdn.microsoft.com/ko-kr/library/h5f7ck28(VS.80).aspx

MFC 확장 DLL은 일반적으로 기존의 MFC 라이브러리 클래스에서 파생된 다시 사용할 수 있는 클래스를 구현하는 DLL입니다.
MFC 확장 DLL에는 다음과 같은 기능 및 요구 사항이 있습니다.
클라이언트 실행 파일은 _AFXDLL이 정의된 상태에서 컴파일된 MFC 응용 프로그램이어야 합니다.
동적으로 MFC에 링크한 기본 DLL에서 확장 DLL을 사용할 수도 있습니다.
확장 DLL은 _AFXEXT가 정의된 상태에서 컴파일되어야 합니다. 그러면 _AFXDLL도 정의되고 MFC 헤더 파일에서 올바른 선언을 가져올 수 있습니다. 또한 DLL을 빌드할 때 AFX_EXT_CLASS가 __declspec(dllexport)으로 정의될 수 있으며, 이러한 정의는 이 매크로를 사용하여 확장 DLL에 클래스를 선언할 경우에 반드시 필요합니다.
확장 DLL은 CWinApp에서 파생된 클래스를 인스턴스화하지 않아야 하며, 클라이언트 응용 프로그램 또는 DLL의 도움을 받아 이 개체를 제공해야 합니다.
그러나 확장 DLL은 DllMain 함수를 제공해야 하며 이 함수에서 필요한 초기화 작업을 수행해야 합니다.
확장 DLL은 MFC의 공유 버전이라고도 하는 MFC의 동적 연결 라이브러리 버전을 사용하여 빌드됩니다. MFC의 공유 버전을 사용하여 빌드된 MFC 실행 파일(응용 프로그램 또는 기본 DLL)만 확장 DLL을 사용할 수 있습니다. 클라이언트 응용 프로그램과 확장 DLL은 모두 같은 버전의 MFCx0.dll을 사용해야 합니다. 확장 DLL을 사용하면 MFC에서 새로운 사용자 지정 클래스를 파생시킨 다음 DLL을 호출하는 응용 프로그램에 이 확장된 버전의 MFC를 제공할 수 있습니다.

댓글 없음:

댓글 쓰기