오후 5:54 2002-08-23
확장DLL을 ActiveX에서 가져다 쓰기
조경민 (bro@shinbiro.com)
=============================================================
문제상황 :
OCX 컴파일시 UI를 갖는 확장 DLL을 가져다 쓸때 아래와 같은
에러가 발생할때는 아래의 얘기를 따라해 봅니다.
OMGroupmapTreeCtrl.obj : error LNK2001: unresolved external symbol
"protected: static struct AFX_MSGMAP const CGroupMapTreeCtrl::messageMap"
(?messageMap@CGroupMapTreeCtrl@@1UAFX_MSGMAP@@B)
OMRankmapTreeCtrl.obj : error LNK2001: unresolved external symbol
"protected: static struct AFX_MSGMAP const CTreeCtrlEx::messageMap"
(?messageMap@CTreeCtrlEx@@1UAFX_MSGMAP@@B)
해결책 :
testdll.dll이라는 MFC 확장 DLL은
testdll.h 에
class AFX_EXT_CLASS CWSocket
{ .. }
로 해서 내주면 된다.
그런후 testocx.ocx에서 testdll.dll을 가져다 쓸 때
Project/Setting에 /MD로 되어있는지 체크한 후
testocx.ocx내의 stdafx.h 를
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
//#define _AFXDLL // <-- MFC Static Link라면 넣어야 한다.
// MFC Shared라면 넣으면 안됨
#include <afxctl.h> // MFC support for ActiveX Controls
#include <afxext.h> // MFC extensions
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Comon Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
// Delete the two includes below if you do not wish to use the MFC
// database classes
#include <afxdb.h> // MFC database classes
#include <afxdao.h> // MFC DAO database classes
#include "testdll.h" // <- 익스포트 헤더파일
------------------------
그 외 관련된 또 다른 문제 상황들.
PRB: Using Extension DLL, Database/OLE/Sockets in Regular DLL
정규DLL에서 확장DLL을 썼을떄 db나 소켓등이 동작 안하면 위의 해결책을 읽어야한다.
/////////////////////
// YourExtDLL.cpp:
#include "afxdllx.h" // standard MFC Extension DLL routines
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization.
if (!AfxInitExtensionModule(extensionDLL, hInstance))
return 0;
}
return 1; // ok
}
// Exported DLL initialization is run in context of application
// or Regular DLL.
extern "C" void WINAPI InitYourExtDLL()
{
// Create a new CDynLinkLibrary for this app.
new CDynLinkLibrary(extensionDLL);
// Add other initialization here.
}
한후 def에 export 함수 하나 더 해주고
/////////////////////
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
확장DLL을 쓰는 정규 DLL에서 초기화 함수를 써줘서 확장DLL에서 정규DLL의
인스턴스를 라이브러리 체인에 제대로 연결 할 수 있도록 한다.
/////////////////////////
// YourRegularDLL.cpp:
class CYourRegularDLL : public CWinApp
{
public:
virtual BOOL InitInstance(); // Initialization
virtual int ExitInstance(); // Termination
// Nothing special for the constructor.
CYourRegularDLL(LPCTSTR pszAppName) : CWinApp(pszAppName) { }
};
BOOL CYourRegularDLL::InitInstance()
{
// Any DLL initialization goes here.
TRACE0("YOUR Regular DLL initializing\n");
// Wire any extension DLLs into CDynLinkLibrary chain.
InitYourExtDLL();
return TRUE;
}
-------------------------------------------------------------------------
문제 상황 TN033 확장DLL을 가져다 쓰는 확장DLL이 있는 상황에 대한 해결책
Limitations of _AFXEXT
이떄엔 AFX_EXT_CLASS를 쓸 수 없다.
A.DLL과 B.DLL이라는 확장 DLL이 있고 B가 A를 쓰는 모양이라면
// A.H
#ifdef A_IMPL
#define CLASS_DECL_A __declspec(dllexport)
#else
#define CLASS_DECL_A __declspec(dllimport)
#endif
class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };
A 컴파일할때는 A_IMPL을 #define 해주고
#define A_IMPL을 A 클래스 헤더 위에 놓던지 stdafx.h에 놓던지
프로젝트 세팅 C++에 A_IMPL을 놓던지.. 해서.
// B.H
#ifdef B_IMPL
#define CLASS_DECL_B __declspec(dllexport)
#else
#define CLASS_DECL_B __declspec(dllimport)
#endif
class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };
이번에 B를 컴파일할떈 B_IMPL을 해야 한다. 따라서 A 라이브러리
가져다쓰는 A 헤더 파일엔 A클래스의 __declspec(dllimport) 버전이
붙게되는 것이다.
확장DLL을 ActiveX에서 가져다 쓰기
조경민 (bro@shinbiro.com)
=============================================================
문제상황 :
OCX 컴파일시 UI를 갖는 확장 DLL을 가져다 쓸때 아래와 같은
에러가 발생할때는 아래의 얘기를 따라해 봅니다.
OMGroupmapTreeCtrl.obj : error LNK2001: unresolved external symbol
"protected: static struct AFX_MSGMAP const CGroupMapTreeCtrl::messageMap"
(?messageMap@CGroupMapTreeCtrl@@1UAFX_MSGMAP@@B)
OMRankmapTreeCtrl.obj : error LNK2001: unresolved external symbol
"protected: static struct AFX_MSGMAP const CTreeCtrlEx::messageMap"
(?messageMap@CTreeCtrlEx@@1UAFX_MSGMAP@@B)
해결책 :
testdll.dll이라는 MFC 확장 DLL은
testdll.h 에
class AFX_EXT_CLASS CWSocket
{ .. }
로 해서 내주면 된다.
그런후 testocx.ocx에서 testdll.dll을 가져다 쓸 때
Project/Setting에 /MD로 되어있는지 체크한 후
testocx.ocx내의 stdafx.h 를
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
//#define _AFXDLL // <-- MFC Static Link라면 넣어야 한다.
// MFC Shared라면 넣으면 안됨
#include <afxctl.h> // MFC support for ActiveX Controls
#include <afxext.h> // MFC extensions
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Comon Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
// Delete the two includes below if you do not wish to use the MFC
// database classes
#include <afxdb.h> // MFC database classes
#include <afxdao.h> // MFC DAO database classes
#include "testdll.h" // <- 익스포트 헤더파일
------------------------
그 외 관련된 또 다른 문제 상황들.
PRB: Using Extension DLL, Database/OLE/Sockets in Regular DLL
정규DLL에서 확장DLL을 썼을떄 db나 소켓등이 동작 안하면 위의 해결책을 읽어야한다.
/////////////////////
// YourExtDLL.cpp:
#include "afxdllx.h" // standard MFC Extension DLL routines
static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization.
if (!AfxInitExtensionModule(extensionDLL, hInstance))
return 0;
}
return 1; // ok
}
// Exported DLL initialization is run in context of application
// or Regular DLL.
extern "C" void WINAPI InitYourExtDLL()
{
// Create a new CDynLinkLibrary for this app.
new CDynLinkLibrary(extensionDLL);
// Add other initialization here.
}
한후 def에 export 함수 하나 더 해주고
/////////////////////
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
확장DLL을 쓰는 정규 DLL에서 초기화 함수를 써줘서 확장DLL에서 정규DLL의
인스턴스를 라이브러리 체인에 제대로 연결 할 수 있도록 한다.
/////////////////////////
// YourRegularDLL.cpp:
class CYourRegularDLL : public CWinApp
{
public:
virtual BOOL InitInstance(); // Initialization
virtual int ExitInstance(); // Termination
// Nothing special for the constructor.
CYourRegularDLL(LPCTSTR pszAppName) : CWinApp(pszAppName) { }
};
BOOL CYourRegularDLL::InitInstance()
{
// Any DLL initialization goes here.
TRACE0("YOUR Regular DLL initializing\n");
// Wire any extension DLLs into CDynLinkLibrary chain.
InitYourExtDLL();
return TRUE;
}
-------------------------------------------------------------------------
문제 상황 TN033 확장DLL을 가져다 쓰는 확장DLL이 있는 상황에 대한 해결책
Limitations of _AFXEXT
이떄엔 AFX_EXT_CLASS를 쓸 수 없다.
A.DLL과 B.DLL이라는 확장 DLL이 있고 B가 A를 쓰는 모양이라면
// A.H
#ifdef A_IMPL
#define CLASS_DECL_A __declspec(dllexport)
#else
#define CLASS_DECL_A __declspec(dllimport)
#endif
class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };
A 컴파일할때는 A_IMPL을 #define 해주고
#define A_IMPL을 A 클래스 헤더 위에 놓던지 stdafx.h에 놓던지
프로젝트 세팅 C++에 A_IMPL을 놓던지.. 해서.
// B.H
#ifdef B_IMPL
#define CLASS_DECL_B __declspec(dllexport)
#else
#define CLASS_DECL_B __declspec(dllimport)
#endif
class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };
이번에 B를 컴파일할떈 B_IMPL을 해야 한다. 따라서 A 라이브러리
가져다쓰는 A 헤더 파일엔 A클래스의 __declspec(dllimport) 버전이
붙게되는 것이다.
'KB > MFC/Win32' 카테고리의 다른 글
process 모니터링 (0) | 2004.03.19 |
---|---|
OLE 자동화시 작업전환 나오는것 안나오게 하기 (0) | 2004.03.19 |
MFC UNICODE 컴파일 하기 (0) | 2004.03.19 |
간단한 LoadString (0) | 2004.03.19 |
Task Scheduler SDK를 이용한 Idle Trigger 생성 예제 (0) | 2004.03.19 |