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
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
Related
I'm currently attempting to compile a VST3 plugin (or any C++ code, for that matter) for the first time, mainly just following Steinberg's own tutorial for all things except the actual sound processing.
Attempting to compile throws an "unresolved external symbol" error:
Error LNK2019 unresolved external symbol "public: __cdecl VSTGUI::VST3Editor::VST3Editor(class Steinberg::Vst::EditController *,char const *,char const *)" (??0VST3Editor#VSTGUI##QEAA#PEAVEditController#Vst#Steinberg##PEBD1#Z) referenced in function "public: virtual class Steinberg::IPlugView * __cdecl Itisdud::Split_TimesController::createView(char const *)" (?createView#Split_TimesController#Itisdud##UEAAPEAVIPlugView#Steinberg##PEBD#Z) Split_Times D:\programme\VST3Dev\Split_times\Split_Times\build\split_timescontroller.obj 1
The function that causes this, createView, is still the default it is when created by the Project Generator:
IPlugView* PLUGIN_API Split_TimesController::createView (FIDString name)
{
// Here the Host wants to open your editor (if you have one)
if (FIDStringsEqual (name, Vst::ViewType::kEditor))
{
// create your editor here and return a IPlugView ptr of it
auto* view = new VSTGUI::VST3Editor (this, "view", "split_timeseditor.uidesc");
return view;
}
return nullptr;
}
Copying the createView function from the again and adelay samples didn't work either.
As the Project generator only includes vstgui4/vstgui/plugin-bindings/vst3editor.h and not the vst3editor.cpp file, I tried including that as well (As I've read that not having the actual implementation there might be the cause of the issue), however that didn't fix the issue but made a lot of other errors happen upon compiling.
I also tried to follow this, including the cpp files noted there and changing the createView function to what is written there, however this also only led to there being a bit more than 300 errors upon compiling.
Copying the includes from the again sample didn't work either.
What would I need to include for this to work?
Those are the linker errors as you didn't instruct the linker where to find the required library files whose functions you are using.
Remember that compilation is a 2-step process that involves compilation and linking so it is best to separate them.
Lets assume you are using Visual Studio on Windows, and lets assume your VST SDK is installed on
C:\VST3SDK.
The first thing you should do is fire-up Visual Studio and select File->Open->CMake and go locate the CMake.txt file here
C:\VST3SDK\VST3_SDK.
After this file is loaded you will find on Visual Studio Solution Explorer a list of ready-made projects that come with the VST SDK loaded.
You will find that one of these projects is called Libraries and that is THE first action you have to do.
Now you have to build the correct library depending on whether you want to make 32-bits or 64-bits VSTs and you should set the configuration of the Libraries project accordingly.
You will build these libraries and if you hadn't changes any setting the libraries will be found at
C:\VST3SDK\VST3_SDK\out\build\x64-Debug\lib
or
C:\VST3SDK\VST3_SDK\out\build\x64-Release\lib
the necessary libraries being:
base.lib
pluginterfaces.lib
sdk.lib
sdk_common.lib
sdk_hosting.lib
vstgui.lib
vstgui_standalone.lib
vstgui.support.lib
vstgui_uidescription.lib
The above step ensures that you now have the necessary library files your VSTs will depend on.
Now assuming you have a VST sample project, lets say that you got from Git-hub and that it were written and setup correctly to run on Visual Studio, i.e. it came with a
myVST.vcxproj file.
Then you could paste the following pragmas on a prominent VST file such as the factory.cpp
#pragma comment(lib, "base.lib")
#pragma comment(lib, "pluginterfaces.lib")
#pragma comment(lib, "sdk.lib")
#pragma comment(lib, "sdk_common.lib")
#pragma comment(lib, "sdk_hosting.lib")
#pragma comment(lib, "vstgui.lib")
#pragma comment(lib, "vstgui_standalone.lib")
#pragma comment(lib, "vstgui_support.lib")
#pragma comment(lib,
"vstgui_uidescription.lib")
(Had to abbreviate due to confusing formatting requirements of this site but replace like "vstgui.lib" with a fully qualified path like
"C:/VST3SDK/VST3_SDK/out/build/x64-Debug/lib/vstgui.lib"
Now if your project properties
C/C++ _> General _> Additional Include Directories has correct entries that will tell the compiler the paths it will find ALL the #include files, then you will find that if you right click on any compilable file (c, cpp, rc ...) and select Compile then the file should successfully compile into an object file without any Compiler errors otherwise it is an indication that the compiler cannot find the required header
files.
But the problem you face are the linker problems, the linker can not find the required libraries of functions you have used in your project and the solution is just pasting the pragmas above.
I've hit a roadblock in attempting to integrate some third-party code in my project. I'm attempting to integrate fontstash, which is a header-only OpenGL text rendering solution. (https://github.com/memononen/fontstash) As a whole, I'm also using SDL, GLEW, AssImp, Lua 5.3/LuaBridge, and Bullet Physics. I've placed the fontstash header files in my vc/include directory. Compilation proceeds normally but linking fails miserably in a huge wall of...
c_main.obj : error LNK2005: "unsigned int __cdecl glfonsRGBA(unsigned char,unsigned char,unsigned char,unsigned char)" (?glfonsRGBA##YAIEEEE#Z) already defined...
c_main.obj : error LNK2005: "void __cdecl glfonsDelete(struct FONScontext *)" (?glfonsDelete##YAXPAUFONScontext###Z) already defined in...
...
c_main.obj : error LNK2005: _stbtt_FindMatchingFont already defined in...
c_main.obj : error LNK2005: _stbtt_GetFontNameString already defined...
It appears to simply iterate the entire list of functions provided via the fontstash header files. I've tried wrapping the headers in an extern "C" {} to no avail. I've tried including the files from the project directory as well. I'm at a loss as to why this would be happening and where to begin figuring out what would be causing it. As indicated in the topic title I'm using MSVC12/Win7, and I'm building for Windows and compiling for x86.
Additionally, I'm including the files more than once as the relevant code that utilizes fontstash is used in other locations. I've thought about this being the issue, but the provided header files from fontstash have inclusion guards so I fail to see why this would occur in that regard.
This is a common problem with the header files, that contain implementaton. When you use #include directive, compiler simply inserts .h file content instead of it. So when you use this header in different places of your project, you get several identical implementations of its methods and global variables. Since it has #ifdef or #pragma once compiler guard, it compiles just fine. But when linker is trying to unite all compiled obj files to one executable module, it gets several identical implementations. Since it could not know which one should be used, you get LNK2005 error. To solve this problem you could move implementations and globals into the separate cpp file and include it in the project. Other way would be to mark all header functions as inline, or use __declspec(selectany)
I have a solution which contains a DLL project and a Win32 EXE project.
I want the EXE project to reference an "Init" function in the DLL.
In the EXE.cpp file I have
extern DWORD __declspec(dllexport) Init(int num);
and I reference it like so
Init(0);
in the EXE project properties, I have gone to the linker's "Additonal Dependencies" and added "mydll.lib", and in the General tab, I have added the directory to where "Additional Library Directories" will point to my DLL's generated mydll.lib file
I do not get any compiler complaints about being able to find the file mydll.lib, but I do get
error LNK2019: unresolved external symbol "unsigned long __cdecl Init(int)" (?Init##YAKI#Z) references in function _wmain
What am I doing wrong to be able to link the DLL that's being built in the same project as my EXE? When I do a dumpbin /exports mydll.lib the only thing I notice is that my Init function lists as _Init
From the comments:
Your DLL was written in C but you are trying to use it from a C++ program. The C++ compiler does not know that it is a C function, it assumes it is a C++ function. Wrap the #include for the .h file with extern "C" {}. – Hans Passant Jul 24 at 22:54
Wow..thanks for the help! Make that an answer and I will accept. I totally forgot to strip the .cpp down to .c for the new project when I added it, and didn't realize that until you said something. This has to do with the way the compiler does name mangling for CPP, am i right? – Derek Jul 24 at 22:56
I'm trying to write a .dll library for .dll injection purposes. And because of this fact, it must have a routine called DllMain, since this is what will be used as the entry point. I think my problem may be stemming from the fact that I'm linking in a static library that I've wrote which utilizes a threads and mutexes from afxmt.h. Because somewhere down the line, the inclusion of this is causing the linker to link from mfcs100ud.lib which apparently contains its own version of DllMain.
Here is the file that is giving me trouble:
dllmain.cpp
#include "stdafx.h"
#include <stdio.h>
#include "NamedPipeLogger.h"
static CNamedPipeLogger m_PipeLogger("Log.txt");
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
}
Here is the stdafx.h file that dllmain.cpp is including.
stdafx.h
#pragma once
#define _AFXDLL
#include <Afx.h>
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
Here is my Error message:
Error 32 error LNK2005: _DllMain#12 already defined in
dllmain.obj D:\xxxxx\xxxxx\xxxxxx\mfcs100ud.lib(dllmodul.obj)
Am I just screwed here because I cannot change the name of my Dll entry point to something other than DllMain?
In many cases this is caused by having _USRDLL in the preprocessor settings, where it should be _LIB. This has to do with 'MFC extension dlls' which I don't think anyone still makes today, yet the VS wizard seems to assume you do want to use this when you check 'Use MFC' in the wizard.
Recently, I experienced the same or a similar issue, and found a solution.
Background
I have an MFC project in Visual Studio 2013 Pro, which generates a DLL. I have several .c modules in the project, which I'm able to do by conditionally specifying the 'extern "C"' construct, disabling precompiled headers for those C files, and - in my case - disabling inherited forced includes, which was pulling-in stdafx.h from the project defaults.
Problem
One day, after having used this method successfully on several C files, when I'd try to add just one more, I'd get the following error.
1>Link:
1> All outputs are up-to-date.
1>mfcs120d.lib(dllmodul.obj) : error LNK2005: _DllMain#12 already defined in MSVCRTD.lib(dllmain.obj)
1> Creating library C:\path\to\project\build_dir\myproj.lib and object C:\path\to\project\build_dir\myproj.exp
1>C:\path\to\project\build_dir\myproj.dll : fatal error LNK1169: one or more multiply defined symbols found
1>
1>Build FAILED.
Solution
I resolved this by implementing "Solution One" from Microsoft Knowledge Base article Q148652, "A LNK2005 error occurs when the CRT library and MFC libraries are linked in the wrong order in Visual C++". This forces the linker to link the libraries in the correct order.
Steps:
Right-click the project, choose Properties.
Ensure you're making changes for All Configurations, and All Platforms.
In the left pane, browse to Linker → Input.
In the right pane, pull down Additional Dependencies, choose <Edit...>.
Add mfcs120d.lib.
Based on the Code Project article Solve error LNK2005: _DllMain#12 already defined in msvcrtd.lib(dllmain.obj) in MFC Projects", I figure I might have to add another library to that list someday, but this much works for me for now.
Well, I guess I threw in the towel on this one (sort of). I was able to at least get by all my problems. I just had to stop using some of the Microsoft classes.
I touched on this in the problem description, but I recall starting to have difficulty with compiling as soon as I started including:
#include <afxmt.h>
#include <afxwin.h>
So I went through and figured out what exactly I was using that required these includes. I was using the AfxBeginThread() method, and the classes CMutex and CCriticalSection. So I figured maybe if I could just get away from any of the proprietary windows stuff that maybe my problems would go away. That means removing all includes of , , and and then address the compilation errors with more standard c++ code. Here is what I did:
Instead of using AfxBeginThread() I used CreateThread().
Instead of using CMutex and CCriticalSection I used the CRITICAL_SECTION structure with its accompanying routines.
After this I was able to compile the .dll and it worked fine.
I got the error when I have moved #include afxdllx.h from dllmain.cpp to StdAfx.h. My project works without this include also
I've opened an old workspace that is a libray and its test harness. It used to work fine but now doesn't and older versions of the code don't work either with the same errors. I've tried recreating the project and that causes the same errors too. Nothing seems out of order in project settings and the code generated works in the main app.
I've stripped out most of the files and got it down to the bare minimum to generate the error. Unfortunately I can't post the project as this is used in production code.
The LNK2001 linker error I get usually means I've left off a library or forgot to implement a virtual function. However this is part of the standard template library - and is a header at that.
The code that is listed as having the problem in IOCompletionPort.obj doesn't actually use std::string directly, but does call a class that does: Comms::Exception accepts a std::string and the value of GetLastError or WSAGetLastError.
The function mentioned in the error (GetMessage) is implemented, but is a virtual function so other classes can override it if need be. However it appears that the compiler has made it as an Ansi version, but I can't find any options in the settings that would control that. I suspect that might be the problem but since there's very little in the way of options for the library I have no way of knowing for sure. However both projects to specify _MBCS in the compiler options.
--------------------Configuration: TestComms - Win32 Debug-------------------- Linking... Comms.lib(IOCompletionPort.obj)
: error LNK2001: unresolved external symbol "public: virtual class
std::basic_string,class
std::allocator > __thiscall
Comms::Exception::GetMessageA(void)const " (?GetMessageA#
Exception#Comms##UBE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ)
Debug/TestComms.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
TestComms.exe - 2 error(s), 0 warning(s)
Any suggestions? I've lost most of the morning to this and don't want to lose most of the afternoon too.
One possibility lies with Win32 ANSI/Unicode "name-mangling", which turns the symbol GetMessage into either GetMessageA or GetMessageW. There are three possibilities:
Windows.h hasn't been loaded, so GetMessage stays GetMessage
Windows.h was loaded with symbols set for ANSI, so GetMessage becomes GetMessageA
Windows.h was loaded with symbols set for Unicode, so GetMessage becomes GetMessageW
If you've compiled two different files in ways that trigger two different scenarios, you'll get a linker error. The error message indicates that the Comms::Exception class was an instance of #2, above -- perhaps it's used somewhere that windows.h hasn't been loaded?
Other things I'd do in your place, just as a matter of routine:
1) Ensure that my include and library paths don't contain anything that I'm not expecting.
2) Do a "build clean" and then manually verify it, deleting any extra object files if necessary.
3) Make sure there aren't any hardcoded paths in include statements that don't mean what they meant when the project was originally rebuilt.
EDIT: Fighting with the formatting :(
#Curt: I think you came the closest. I haven't tested this but I think I sort of gave the answer in my original question.
GetMessage is a define in Windows.h wrapped in a ifndef block to switch between Ansi (GetMessageA) and Unicode (GetMessageW).
Presuming you haven't futzed around with the Project settings deleting something you ought not have (which is where I'd expect external dependencies like User32.lib to be):
Check Tools | Options | Directories | Libraries (going from memory here) and ensure that you're not missing the common-all-garden variety lib directories (again, without VC6 in front of me, I can't tell you what they are)
This is a general problem with the way Microsoft handled the ANSI vs. Unicode APIs. Since they are all (or pretty much all) done by defining macros for the function names that resolve to the 'A' or 'W' versions of the function names you cannot safely have an identifier in your namespace/class/struct/enum/function that matches a Windows API name.
The windows.h macros run roughshod over all other namespaces.
windows.h is declared at the top of IOCompletionPort.h as an include - I was sick of seeing 7 lines just to include 1 file so I have wrapped it its own file and includes that itself. This also contains some additional #defines (i.e. ULONG_PTR) as our main app won't compile with the Platform SDK installed:-(
That is confirmed. Nothing is out of place.
I've done that - deleted the build directories
I never use hard-coded paths.