Can't get rid of LNK 2019 error in Dll - c++

I keep getting link 2019 errors on this ctor,ctor-copy ctor-assignment code that works in other projects with no errors. I am trying to include it in a plain DLL generated with the MFC support option checked. I'm in VS2010.
#include "stdafx.h"
#include "Name.h"
CNameBase::CNameBase()
{
IsGlobal = false;
UseShortName = true;
m_ShortName = NO_NAME_ID ;
m_Description = "";
pMe = this;
}
CNameBase::CNameBase( const CNameBase& ref )
{
m_Description = ref.m_Description;
IsGlobal = ref.IsGlobal;
m_LongName = ref.m_LongName;
m_ShortName = ref.m_ShortName;
UseShortName = ref.UseShortName;
pMe = ref.pMe;
}
CNameBase& CNameBase::operator=( const CNameBase& ref )
{
m_Description = ref.m_Description;
IsGlobal = ref.IsGlobal;
m_LongName = ref.m_LongName;
m_ShortName = ref.m_ShortName;
UseShortName = ref.UseShortName;
pMe = ref.pMe;
return *this;
}
The link errors are:
error LNK2019: unresolved external symbol "public: __thiscall CNameBase::CNameBase(void)" (??0CNameBase##QAE#XZ) referenced in function "public: __thiscall CName::CName(void)" (??0CName##QAE#XZ)
1>clayer.obj : error LNK2019: unresolved external symbol "public: __thiscall CNameBase::CNameBase(class CNameBase const &)" (??0CNameBase##QAE#ABV0##Z) referenced in function "public: __thiscall CName::CName(class CName const &)" (??0CName##QAE#ABV0##Z)
1>clayer.obj : error LNK2019: unresolved external symbol "public: class CNameBase & __thiscall CNameBase::operator=(class CNameBase const &)" (??4CNameBase##QAEAAV0#ABV0##Z) referenced in function "public: class CName & __thiscall CName::operator=(class CName const &)" (??4CName##QAEAAV0#ABV0##Z)
1>C:\devt\hftappb\Debug\CLayer.dll : fatal error LNK1120: 3 unresolved externals
The funny thing is this code works and has worked. The Ctors do what they're supporsed to do and have been in other solution. I stick the class in this file and suddenly get these errors that I am having dififculty resolving. I've compared project settings between this project and projects I know this code works in. What else could be causing this?

The cpp file that holds the implementation of the 3 functions doesn't compile/link into the exe/dll.
If you're using C++ namespaces, you need to make sure that both header and cpp use it. The namespace is part of the class name.

Thank you all for responding to my question. The question took the better part of a day to resolve but I wanted to share the answer with others since it can happen to anyone. The solution to the problem wasn't any code, it was a configuration issue. In VS2010, apparently, ALL files that your project references must be in the list of files that appear with the project in the Solution Explorer. I am not privy to the underlying architecture so I can't answer why this is required. On the surface, there's NO reason for it. If there are files #included into a project either explicity or implicitly through the Project paths and whose functions I reference from files that are included in the Project's list of files in Solution Explorer, functions in those files should be able to reference functions in files that aren't included in the project filelist in Sol Exp.
The rules for #include and other rules are convoluted enough in C++ without MSFT adding their layers of confusion. These types of errors would be easily prevented with better error reporting and/or UI management.
The rules I've learned are this
1. Never make more than 1 copy of the same file in the entire solution. Multiple copies of the same file are hard to keep symchronized and lead to confusion as to which one is being used.
2. All files being used in a project must be listed in that project but rule 1 should be respected.
Steps (approximate)
1. Create a project
2. Create a .h and .cpp with global functions (or in a class doesn't matter)
3. In the same parent directory as project 1, create project 2 There should be two project directories underneath one parent
4. In project 2 in File Explorer, create a subfolder called Common
5. Create a .h and .cpp in that folder and create a simple function that returns a value
6. Add those files to project 2 in Solution Explorer
7. In Project 1, in the .cpp, create a function that #includes the file for project 2 and calls that function in that file.
8. The compiler generates a 2019 and 2001 unresolved external link error. What it should do is report that those files are required to be in your project's file list.

Related

Unresolved externals with google test

I have a project I am trying to add google-test unit testing to. It is structured like so:
VM (project)
some source files
BytecodePrograms.h
VMTest (project, made by add project -> google test -> link dynamically, test VM)
pch.h
test.cpp
I added my VM project as an include directory in VMTest properties -> c/c++ -> general -> additional include directories
contents of test.cpp are:
#include "pch.h"
#include "BytecodePrograms.h"
TEST(TestCaseName, TestName) {
EXPECT_EQ(8, VMFibonacciImp(6));
EXPECT_TRUE(true);
}
If I build, I get the following errors
Error LNK2019 unresolved external symbol "public: __thiscall WVM::WVM(void)" (??0WVM##QAE#XZ) referenced in function "int __cdecl VMFibonacciImp(int)" (?VMFibonacciImp##YAHH#Z) WVMTest C:\Users\WadeMcCall\source\repos\Virtual Machine Visual Scripting\WVMTest\test.obj 1
Error LNK2019 unresolved external symbol "public: __thiscall WVM::~WVM(void)" (??1WVM##QAE#XZ) referenced in function "int __cdecl VMFibonacciImp(int)" (?VMFibonacciImp##YAHH#Z) WVMTest C:\Users\WadeMcCall\source\repos\Virtual Machine Visual Scripting\WVMTest\test.obj 1
Error LNK2019 unresolved external symbol "public: int __thiscall WVM::interpret(class std::vector<int,class std::allocator<int> >)" (?interpret#WVM##QAEHV?$vector#HV?$allocator#H#std###std###Z) referenced in function "int __cdecl VMFibonacciImp(int)" (?VMFibonacciImp##YAHH#Z) WVMTest C:\Users\WadeMcCall\source\repos\Virtual Machine Visual Scripting\WVMTest\test.obj 1
However, my VM project defines my WVM class and uses it and can build and run and BytecodePrograms.h includes VM.h which has the declaration for this class.
I feel like this must just be a problem with the set up of my projects in Visual Studio somehow, but I have no idea. I have been googling for 2 days straight and have found other people with similar problems but their solution never seems to work for me.
Any ideas? Thanks.
I found a solution here: https://stackoverflow.com/a/19709712/8488701
Similar to what Steve suggested, except instead of creating a whole new project, I use a post-build event to build my project to a library and then link google test to that. The advantage of this over Steve's solution is that you don't have to modify your main project at all and you can still build a unit testing project on top of it.
This is a link error indicating that it found the .h file but couldn't find the actual implementation found in the .cpp. If you have a LIB project then visual studio may take the cpp code compiled into the LIB project and add it to your EXE project.
To incorporate the code into the test project, you have two options.
You can add the .cpp files in your VM Project to your Test project as well, but this is not usually done.
Instead, if your VM project is now an EXE I would recommend creating a new project called VMLib as a LIB project and then adding that project to both the test project and the VM EXE project.

Linker error while unit testing with Visual Studio C++

I want to unit test my C++ project with Visual Studio. After adding the folders from my project as include path to my test project, I get linker errors when trying to compile the tests:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __thiscall Piece::Piece(enum Color)" (??0Piece##QAE#W4Color###Z) referenced in function "public: __thiscall Bishop::Bishop(enum Color)" (??0Bishop##QAE#W4Color###Z) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
Error LNK2019 unresolved external symbol "public: __thiscall Board::~Board(void)" (??1Board##QAE#XZ) referenced in function "public: void __thiscall ChessPlusPlusTests::BishopTests::ValidMovesTest(void)" (?ValidMovesTest#BishopTests#ChessPlusPlusTests##QAEXXZ) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
Error LNK2019 unresolved external symbol "public: void __thiscall Board::placePieceAt(class Piece * const,struct Position)" (?placePieceAt#Board##QAEXQAVPiece##UPosition###Z) referenced in function "public: void __thiscall ChessPlusPlusTests::BishopTests::ValidMovesTest(void)" (?ValidMovesTest#BishopTests#ChessPlusPlusTests##QAEXXZ) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
Error LNK2001 unresolved external symbol "public: virtual class std::vector<struct Position,class std::allocator<struct Position> > __thiscall Bishop::getMovesFor(struct Position,class Board &)" (?getMovesFor#Bishop##UAE?AV?$vector#UPosition##V?$allocator#UPosition###std###std##UPosition##AAVBoard###Z) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
Error LNK2001 unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Bishop::toString(void)" (?toString#Bishop##UAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
Error LNK2001 unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Bishop::toShortString(void)" (?toShortString#Bishop##UAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) ChessPlusPlus-Tests D:\Documents\Projects\ChessPlusPlus\ChessPlusPlus-Tests\BishopTests.obj 1
My test source code:
#include "stdafx.h"
#include "CppUnitTest.h"
#include "Bishop.h"
#include "Board.h"
#include "TestUtils.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ChessPlusPlusTests
{
TEST_CLASS(BishopTests)
{
public:
TEST_METHOD(ValidMovesTest)
{
// Arrange
Board board{};
Bishop *piece = new Bishop{ Color::WHITE };
Position pos{ 3,3 };
board.placePieceAt(piece, pos);
// Act
auto validPositions = piece->getMovesFor(pos, board);
// Assert
TestUtils::AssertPositions(validPositions, {
0,0,0,0,0,0,0,1,
1,0,0,0,0,0,1,0,
0,1,0,0,0,1,0,0,
0,0,1,0,1,0,0,0,
0,0,0,0,0,0,0,0,
0,0,1,0,1,0,0,0,
0,1,0,0,0,1,0,0,
1,0,0,0,0,0,1,0,
});
}
};
}
Without adding the include path's the test project doesn't compile, since the header file includes in the main project rely on the include paths.
The main project compiles just fine.
Can someone help me to understand whats going wrong?
Thanks!
I believe the chosen answer is not correct. Tests typically should be run in their environment; therefore, they should not access the implementation (.cpp)
When you create a separate Test Project on Visual Studio (VS 2017) you need to create a reference to the project you want to test (right-click test project -> Add -> Reference -> tick projects):
Add a reference
If you see some linker errors, right-click from the Unit test project: Project->Linker->Input->Additional Dependencies->Edit
then add the path to your .obj files.
You could try something like "$(SolutionDir)ConsoleApplication1\$(IntDir)*.obj" where ConsoleApplication1 is the target project name.
Path to .obj
Initially, I only wanted to put a comment on Cornelis' post, but I couldn't.
https://www.codeproject.com/Tips/1085171/How-To-Do-Unit-Testing-with-Cplusplus-in-Visual-St
I found there that you have to add your .h and .cpp files as existing files also to the test project. That is left out on the official documentation or I missed it.
Now it works!
I just ran into the same problem and solved it differently, following this piece of Microsoft documentation: https://learn.microsoft.com/nl-nl/visualstudio/test/unit-testing-existing-cpp-applications-with-test-explorer?view=vs-2015&redirectedfrom=MSDN#objectRef
This solution is a bit cleaner, I think, as you don't end up with all the header files from your projects under test also showing up in your test project.
Lines from the documentation in italics, bold lines are my additions:
If the code under test does not export the functions that you want to test, you can add the output .obj or .lib file to the dependencies of the test project.
Create a C++ test project.
On the File menu, choose New, Project, Visual C++, Test, C++ Unit Test Project.
Make sure to add the projects that you want to test as References. If you forgot, you can also add these references later, in the Solution Explorer window.
In Solution Explorer, on the shortcut menu of the test project, choose Properties. The project properties window opens.
Choose Configuration Properties, Linker, Input, Additional Dependencies.
Choose Edit, and add the names of the .obj or .lib files. Do not use the full path names.
For me, there were only .obj files. I found them in the Intermediates folder, of which there are multiple versions, one for each combination of Solution Platform (x86 or x64) and Solution Configuration (Debug or Release). If you have a lot of .obj (or .lib) files, I found it convenient to open a terminal and run ls (or dir) to get the filenames, edit out the .log, .txt and .pdb filenames that I didn't need, and copy paste the list of .obj filenames into Visual Studio. For convenient editing, note that you can click on the dropdown arrow on the right hand side of the Additional Dependencies entry field and click on edit.
Choose Configuration Properties, Linker, General, Additional Library Directories.
Choose Edit, and add the directory path of the .obj or .lib files. The path is typically within the build folder of the project under test.
For me, I only had .obj files. I found them in the Intermediates folder, of which there are multiple versions, one for each combination of Solution Platform (x86 or x64) and Solution Configuration (Debug or Release). A convenient macro for setting this path for all 4 combinations is this: $(SolutionDir)bin\$(PlatformTarget)\$(IntermediateOutputPath)Intermediates. You might have to take out the bin\ part, as I have also seen the output folders set up directly in the Solution Directory, instead of in a separate binary folder.
Choose Configuration Properties, VC++ Directories, Include Directories.
Choose Edit, and then add the header directory of the project under test.
For this directory, it's okay to point directly to folders that are part of the project under test. There is no need to copy the header files over to the test project. It's also okay if this directory contains more than just the headers. For example, my source folder contains both the .h files and the .cpp files.
After following these steps, I was able to include the header files in my test code by simply writing:
#include "SomeHeaderName.h"
So, without any need to specify the folders that the header files are in.
Make sure to clean and rebuild your entire solution. Then, your tests should be able to access the functionality of the projects that you are testing.

Unresolved externals when compiling unit tests for Visual C++ 2012

I want to create unit tests for a Visual C++ project. I tried following these MSDN instructions. I've found pages where they differentiate between unmanaged/mixed/pure code, but I don't fully understand those concepts. My code doesn't use .NET and would likely compile under MinGW with a few code adjustments.
My main project builds an executable, so I followed the steps under To reference exported functions from the test project. For starters I got different project options:
I went with Native Unit Test Project. I added a reference to my main project and I set Include Directories to $(SolutionDir)\Cubes;$(IncludePath). I wrote my code and got this when compiling:
1>Creating library C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.lib and object C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.exp
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Room::Room(void)" (??0Room##QAE#XZ) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: __thiscall Layout::Layout(class Room *,int)" (??0Layout##QAE#PAVRoom##H#Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::add(int,int,class Room *)" (?add#Layout##QAEXHHPAVRoom###Z) referenced in function "public: void __thiscall CubesTest::LayoutTest::NumOfRoomsConsistency(void)" (?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ)
1>LayoutTest.obj : error LNK2019: unresolved external symbol "public: void __thiscall Layout::clear(int,int,bool)" (?clear#Layout##QAEXHH_N#Z) referenced in function __catch$?NumOfRoomsConsistency#LayoutTest#CubesTest##QAEXXZ$0
1>C:\Users\Pieter\Dropbox\Unief\TTUI\TTUIproject\Cubes\Debug\CubesTest.dll : fatal error LNK1120: 4 unresolved externals
If I'm not mistaken, this means that the compiler finds the header files, but not the source files. What am I missing?
Here is a step-by-step description on how to add an EXE as an unit-test target.
The key point is to "export" the functions/classes you want to test... You can download the complete sample here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip (I did not change any project settings, so all changes you can see in the source-code; of course, some parts can be made in the project settings).
Create a Win32 Application (Console or MFC or Windows, does not matter); I created a console project called CPP_UnitTestApp:
Add a function you want to test (you can also add classes). For example:
int Plus1(int i)
{
return i+1;
}
Add a header file for the functions you want to test: CPP_UnitTestApp.h
Put the declaration of the methods into the header file, and also export these functions!
#pragma once
#ifdef EXPORT_TEST_FUNCTIONS
#define MY_CPP_UNITTESTAPP_EXPORT __declspec(dllexport)
#else
#define MY_CPP_UNITTESTAPP_EXPORT
#endif
MY_CPP_UNITTESTAPP_EXPORT int Plus1(int i);
Include this header file in the main-cpp (here CPP_UnitTestApp.cpp) and define the EXPORT_TEST_FUNCTIONS before including the header:
#define EXPORT_TEST_FUNCTIONS
#include "CPP_UnitTestApp.h"
Now add a new project (Native unit test project: UnitTest1)
Include the header and the lib to the "unittest1.cpp" file (adopt the paths as you want):
#include "..\CPP_UnitTestApp.h"
#pragma comment(lib, "../Debug/CPP_UnitTestApp.lib")
Go to the project settings of the test project add add a reference to the "UnitTest1" project (Project|Properties|Common Properties|Add New Reference...: Select under "Projects" the "CPP_UnitTestApp"-Project)
Create the unit test function:
TEST_METHOD(TestMethod1)
{
int res = Plus1(12);
Assert::AreEqual(13, res);
}
Run your unit test ;)
As you can see, the main point was to export the function declaration! This is done via __declspec(dllexport) even if it is an EXE.
As I said, the demo project can be downloaded here: http://blog.kalmbachnet.de/files/CPP_UnitTestApp.zip

Error LNK 2019 unresolved external symbol from header file from my professor

So I'm pretty new to C++ programming and am taking a class on it but am having some trouble with an assignment because I am getting an error I can't seem to fix. The assignment is to create a composite class out of a number of classes using a string class the professor gave us. The problem I'm having is that I'm getting an unresolved external symbol error from the header file he gave us and I don't know why. I added the folder containing the header file and the associated cpp file using Properties -> C/C++ -> General -> Additional Include Directories and then used #include in the header file for my class but I'm getting 2 errors when I try to build it, the program compiles just fine. It's strange that I'm only getting 2 errors when there are many more functions in WCS_String that don't return an error.
Here are the error codes I'm getting:
1>Name.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall WCS_String::~WCS_String(void)" (??1WCS_String##UAE#XZ) referenced in function __unwindfunclet$??0Name##QAE#XZ$0
1>Name.obj : error LNK2019: unresolved external symbol "private: void __thiscall WCS_String::LocalCopy(char const *)" (?LocalCopy#WCS_String##AAEXPBD#Z) referenced in function "public: __thiscall WCS_String::WCS_String(char const *)" (??0WCS_String##QAE#PBD#Z)
If anyone could help me it would be greatly appreciated as I have run into a dead end with my limited programming knowledge. If you need any more information in order to help me please just ask.
If I were you I would just copy all the professor files to the project directory, and add both header and source files to it.
If you have .o or .obj files associated with your WCS_String class, you need to tell your linker where to find them.

LNK 2028 - 2019 / Managed and Unmanaged C++ ? (VS 2008)

I am trying to link an open-source library to one of my project. The library is unmanaged (named Tetgen) and my project is in managed C++.
My project recognizes the header and can use the functions defined in it. But I get a 2028 error each time it wants to access to some methods defined in the .cpp:
error LNK2028: unresolved token (0A000E20) "public: void __thiscall tetgenio::save_nodes(char const *)" (?save_nodes#tetgenio##$$FQAEXPBD#Z) referenced in function "public: virtual bool __thiscall ForwardModelingPlugin::CustomMeshVol3D::tesselate(void)" (?tesselate#CustomMeshVol3D#ForwardModelingPlugin##$$FUAE_NXZ)
I have tried to create a test function:
int tetgenio::Test(int i) {
return i;
}
...and another Testbis function, defined in the header. Testbis works, Test gives a 2028 error.
I have compared the .obj of my project and the .lib created, and for the lib there is:
save_nodes#tetgenio##QAEXPAD#Z
But in the .obj it is:
save_nodes#tetgenio##$$FQAEXPBD#Z in the .obj
It appears they are not the same.
Everything is compiled with /clr. I've tried creating both a .lib and a .dll, with same results either way.
That was because of a linker problem linking to different folders containing the same files.