Question

I'm working my first internship, still trying to get this horrible thing to compile on Visual Studio 2008. I've spent a week playing around with IDE settings and Windows SDK installs and I don't think I'm going to make any more headway in that direction. Everybody is out on vacation here and I have no senior engineers to turn to. Help me Stack Overflow, you're my only hope!

Today, I'm trying to follow the specific errors so I have some idea why everything's breaking. Perhaps then I'll have better insight into how to fix it. For the last couple of hours I've been working on this one:

6>ResizableLib.lib(ResizablePage.obj) : error LNK2001: unresolved external symbol "public: virtual int __thiscall CWnd::Create(char const *,char const *,unsigned long,struct tagRECT const &,class CWnd *,unsigned int,struct CCreateContext *)" (?Create@CWnd@@UAEHPBD0KABUtagRECT@@PAV1@IPAUCCreateContext@@@Z)

My understanding is that the CWnd::Create function cannot be found from inside the ResizableLib project which I'm working with. I figured I'd find the file where it was being called, and trace the includes to see if it should have a definition for CWnd::Create at the point where it was being called. I started by searching the entire project (alt+E+F+I) for Create( since I figured this would get every instance where the Create function was being called. I found several other calls to functions that ended with Create, but only one that appeared to be calling the Create function itself:

ResizableGrip.cpp(127): BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS

So... I opened up ResizableGrip.cpp and looked at the includes. The first line of the file was:

#include "stdafx.h"

I figured I'd go check out that file to see if there was a function declaration for CWnd::Create, or perhaps some sort of inherited version of it. There were no preprocessor conditions for including this file (as there are at many other points in this program), so I figured it was safe to say that stdafx.h would be included. In order to figure out which stdafx.h file would be included (what is an stdafx.h file typically used for anyway? I see them all over the place!), I first looked in the same directory as the ResizableGrip.cpp file because I believe the compiler first looks in the same directory as the including file before checking the additional includes path in the project, followed last by the include path listed in the main Visual Studio VC++ settings. Is this correct? At any rate, there was an StdAfx.h file located in the same directory, so I concluded that this would be the one that got included. The first few lines of the file looked like this:

#if !defined(AFX_STDAFX_H__0A781DD9_5C37_49E2_A4F5_E517F5B8A621__INCLUDED_)
#define AFX_STDAFX_H__0A781DD9_5C37_49E2_A4F5_E517F5B8A621__INCLUDED_
#pragma message("StdAfx CommonClasses/ResizableLib")
#ifdef INC_DEBUG
#pragma message("In ResizeLib::StdAfx.h") 
#endif

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#if _MSC_VER >= 1300
#define  WINVER      0x0500
#define _WIN32_WINNT 0x0500
#endif

#define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>         // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT

I'll admit I don't fully understand all of the preprocessor things that are going on here, but since there are no conditionals surrounding #include , I'd assume that it's getting included too. There was no afxwin.h file in the project directory, so I looked at the additional includes for the project. The only specified place to look was ....\COMMON, so I went two directories out, located the COMMON folder, and looked for afxwin.h. There was nothing there, so I looked in the IDE settings for VC++ directory includes. The first listing was: $(WindowsSdkDir)\include so I looked up the WindowsSdkDir environment variable, which of course didn't exist. I checked in the registry as well. No dice. Eventually I figured out that you can resolve these symbolic names by clicking on one of the ellipses (...) that appear at the far right end of the text fields in the project configuration windows that appear when you click on them and expanding the Macros pane. By doing this, I discovered that $(WindowsSdkDir) was pointing to: C:\Program Files\Microsoft SDKs\Windows\v6.0A\ so I went there, opened up the Include folder, and found no afxwin.h file. $(FrameworkSDKDir)include pointed to the same place as $(WindowsSdkDir)\include, so I proceeded to the next line in the Visual Studio VC++ Directory include list: $(VCInstallDir)atlmfc\include which resolved to C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\ where I finally found afxwin.h. In this file there was finally a class called Cwnd with a function called Create defined as such:

virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);

I have no idea what any of those parameters are, but I'm operating off the assumption that this is an extremely redefined version of the function which the linker was originally whining about:

CWnd::Create(char const *,char const *,unsigned long,struct tagRECT const &,class CWnd *,unsigned int,struct CCreateContext *)

Otherwise, wouldn't the compiler catch this as a different version of the function before the linker took over? Actually, now that I think about it (hence the entire reason for my posting), I guess all I did was walk through the code the same way I'd troubleshoot a compiler error. Did I even do that right? This thing is a monster and I'm just taking guesses here.

So again, like the title says, how are you supposed to follow a linker error? Is there a similar process to what I've done here? The MSDN article makes it sound like this error occurs when the code works fine and the compiler somehow manages to lose the .obj file or .lib file. How can I get it to point to the right place again?

Ugh, -Alex

Was it helpful?

Solution

A linker error means it's found the header but couldn't find the implementation (obj or lib). There's no point checking whether the header exists - your code has compiled, therefore the compiler found the header.

It looks like you need to link against MFC (ie. the lib that includes the CWnd implementation).

In your project properties, set:

General > Use of MFC > Use MFC in a Shared DLL

As for stdafx.h, it's a precompiled header. You can read up on those yourself. ;) If you don't want it, you can turn it off in project properties:

C/C++ > Precompiled Headers > Precompiled Header > Not Using Precompiled Headers
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top