Linking in MFC Extension DLL's

Posted on 1997-09-29
Last Modified: 2013-11-20
Environment Visual C++ 5.0, NT 4.0

I am having trouble getting two MFC extension DLL's to link together. I have an extension DLL that contains a view and various functions and classes for that view. If I link this to an MFC EXE, all is fine.

However I want to link this to another MFC extension DLL that is then linked into an EXE. When I do this it fails to link correctly, giving the error:

--------------------Configuration: test2 - Win32 Debug--------------------
   Creating library Debug/test2.lib and object Debug/test2.exp
DibView.obj : error LNK2001: unresolved external symbol "public: static struct CRuntimeClass const  AZDIBVIEW::classAZDIBVIEW" (?classAZDIBVIEW@AZDIBVIEW@@2UCRuntimeClass@@B)
DibView.obj : error LNK2001: unresolved external symbol "protected: static struct AFX_MSGMAP const  AZDIBVIEW::messageMap" (?messageMap@AZDIBVIEW@@1UAFX_MSGMAP@@B)
Debug/test2.dll : fatal error LNK1120: 2 unresolved externals
Error executing link.exe.

test2.dll - 3 error(s), 0 warning(s)

Is there a reason that I can not link two MFC extension DLL's together? The following extract is from the header file, and cpp file for the first extension DLL. the second extension DLL just adds a new class based on a CView (as with the EXE that I tested in originally) and then I replace CView with AZDIBVIEW.

The header of the first extension DLL is:

class AFX_EXT_CLASS AZDIBVIEW : public CView

friend class AZDRAWANNOTOOL;
friend class AZDRAWANNO;
friend class AZRECTANNOTOOL;
friend class AZDRAWRECT;

AZDIBVIEW();           // protected constructor used by dynamic creation

// These functions can be called from anywhere that has a pointer to the
view. They
// are used to control the image and the annotations used by the view.
Annotations are
// added through the document, and can be removed as a whole by the
document. Individual
// annotaions are removed by selecting and then removing from the view.
BOOL ToggleAnnoTips();
BOOL ToggleAnnotations();
void DeleteSelectedAnnos();
static void UpdateDIBViews();
void SetUserTool( AZTOOL tool );
void SetUserMode( AZMODE mode );
int GetZoomPercent();

// These are the overidable functions that should be called from your view.
virtual void GetViewMenu( CMenu&entA menu ) { popupviewmenu = FALSE; }
virtual void GetAnnoMenu( CMenu&nutA menu ) { popupannomenu = FALSE; }
virtual CSize GetImageSize();

virtual CDrawObjList* GetObjects() = 0;//{ return NULL; }
virtual void Remove( AZDRAWANNO* pObj ) = 0;//{;}
virtual AZDIB* GetDIBImage() = 0;//{ return NULL; }
virtual void DrawAnnotations( CDC* pDC ) = 0;//{;}
virtual AZDRAWANNO* ObjectAt( const CPoint&onsn point, AZDIBVIEW* pView ) =
0;//{ return NULL; };
virtual void Add( AZDRAWANNO* pObj ) = 0;//{;}

// ClassWizard generated virtual function overrides
virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD
dwStyle, const RECT&Name rect, CWnd* pParentWnd, UINT nID, CCreateContext*
pContext = NULL);
virtual void OnInitialUpdate();     // first time after construct
virtual void OnDraw(CDC* pDC);
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
virtual void OnActivateView(BOOL bActivate, CView* pActivateView, CView*

// Implementation
virtual ~AZDIBVIEW();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext&sEWV dc) const;

// Generated message map functions
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnUpdateZoomtool(CCmdUI* pCmdUI);
afx_msg void OnUpdateSelecttool(CCmdUI* pCmdUI);

// These functions and variables are for use within the class and by its
friend classes
// only. Don't tamper with them, you are likely to corrupt the image of the
DLL that is
// being used by your software, this will give serious bugs in your code.
virtual BOOL IsAnnotationsOn();

// functions for dealing with annotation tips
BOOL HoldUpAnno( CRect&nsOn position, CPoint point );
BOOL IsAnnoTipsOn();
void KillTimedTips();
void TimedTips( CPoint imagepoint, CPoint screenpoint );
void MoveTips(  CPoint imagepoint, CPoint screenpoint  );
void HideTips();
void DrawTips(  CPoint imagepoint, CPoint screenpoint  );

// functions for dealing with annotations and annotations list
AZDRAWANNO* GetLastAnnotation();
AZDRAWANNO* GetNextAnnotation( POSITION&ionA pos );
POSITION GetAnnotationHeadPos();
AZDRAWANNO* GetFirstAnnotation();
int SelectedAnnotations();
BOOL IsSelected( AZDRAWANNO* pObj );
BOOL CheckForObjectEdge( CRect rect );
void RemoveViewAnno( AZDRAWANNO* pObj );
void SelectWithinRect( CRect rect, BOOL bAdd );
void DeSelect( AZDRAWANNO* pObj );
void Select( AZDRAWANNO* pObj, BOOL bAdd = FALSE );
void InvalObj( AZDRAWANNO* pObj );

// functions for mapping between client and image space
void ClientToDoc( CPoint&Rect point );
void ClientToDoc( CRect&Rec rect );
void DocToClient( CPoint&Rect point, AZHANDLE pixel = CENTER );
void DocToClient( CRect&Rec rect, AZHANDLE pixel = CENTER );
BOOL ResetScrollBars( CPoint point );
void ClientToScrollValue( CPoint&llVa clientpoint );
void ScrollToClientValue( CPoint&ntVa clientpoint );
BOOL IsImageScrolled( UINT nBar );
SCROLLINFO GetScrollInfo( int nBar, UINT nMask = SIF_ALL );

// functions for dealing with zooming
void ZoomImage( CPoint point );
AZMODSIDE FindZoomSide( CRect zoomrect );

// functions for updating and drawing the client space
void ScrollDIB( UINT bar, UINT nSBCode, UINT nPos );
void UpdatePartialArea( CDC* pDC, CRect clientrect );
void UpdateClientArea( CDC* pDC, CRect clientrect, BOOL realimage =
BOOL IsActive();

// variables defined here

and then its corresponding cpp file includes the following lines. I have
removed any additional functions, as I guess they should not affect whether
the MSG_MAP can be resolved.



Thanks in advance,
Spencer Jones,
Azure Limited.
Question by:sdj
LVL 15

Expert Comment

by:Tommy Hui
ID: 1307127
When you link in an import library (which is what an extension DLL will produce as well as the .DLL), all that means to to the linker is, "if my target uses anything from this library, make a reference to it". But the important thing to remember is that the linker does not copy the import library into your target (otherwise, it defeats the purpose of DLLs). So your all-purpose extension DLL does not have a copy of the specialized extension DLL. And when you create your exe, you must specify all the import libraries it needs: In this case, both extension DLLs.

Author Comment

ID: 1307128
I'm not sure whether you misunderstood my question or I am missing the point of your answer? This works:

MFC EXTENSION (withview) -- MFC EXE (using view)

This does not:

MFC EXTENSION1 (with view) -- MFC EXTENSION2 (using view)

MFC EXTENSION2, includes the lib file for MFC EXTENSION1, as with the EXE example that *does* work. However MFC EXTENSION2 compiles but fails to link for the RUNTIME CLASS and MSG_MAP information. Everything else is linking fine. Why is the RUNTIME CLASS and MSG_MAP not being exported for MFC_EXTENSION2?

Accepted Solution

jaba earned 50 total points
ID: 1307129
The problem is with  AFX_EXT_CLASS macro.
This macro is defined by MFC as __declspec(dllexport) when the preprocessor symbols _AFXDLL and _AFXEXT are defined.
When you including first DLL include file to second MFC extention it macro EXPORTING class , not importing :-)
Because _AFXDLL and _AFXEXT also defined in second DLL project.

Solution is :
In the end of stdafx.h add :
// "MY" word different for different MFC extentions :-)
In your include file add:

#ifndef MY_EXT_CLASS
class MY_EXT_CLASS CMyExportingClass

this declaration exporting class when you inside class` project and importing in all other projects


Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Change owner from userA to server Local Administrators 7 59
Hibernate methods 2 68
sum28 challenge 31 106
matchUp  challenge 9 94
Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now