I seem to have some issues with creating new files for my project.
The issue is that in my sk_error.h file it seems to complain about unresolved external symbols (full error report below). When I place my OutOfRange class in my sk_interface.h file no one complains but when I put the class in the errors file it has issues with it.
If I was to comment out OutOfRange it works perfectly fine so I dont think that it is an issue with the DLL setup.
sk_error.h
#include <sk_platform.h>
#include <sk_interface.h>
namespace sky {
class SK_API OutOfRange : IError {
public:
OutOfRange() {
m_message = " Out Of Range";
m_value = (0 << 1);
}
std::string getMessage() override {
return m_message;
}
};
}
sk_platform.h
#if defined (SK_NONCLIENT_BUILD)
#ifndef SK_API
#define SK_API __declspec(dllexport)
#endif
#else
#ifndef SK_API
#define SK_API __declspec(dllimport)
#endif
#endif
sk_interface.h
#include <sk_platform.h>
#include <string>
namespace sky {
...
class SK_API IError {
public:
virtual std::string getMessage() = 0;
protected:
uint32_t m_value = 0;
std::string m_message = "Error not initialized";
};
}
The Client Project using the DLL
#include <sk_logmanager.h>
#include <sk_error.h>
#include <iostream>
int main() {
sky::g_LogManager.startup();
sky::OutOfRange err;
std::cout << err.getMessage() << "\n";
sky::g_LogManager.shutdown();
while (1) {}
}
Error Output
1>------ Build started: Project: SkyTest, Configuration: Debug Win32 ------
1>main.cpp
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall sky::OutOfRange::OutOfRange(void)" (__imp_??0OutOfRange#sky##QAE#XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall sky::OutOfRange::getMessage(void)" (__imp_?getMessage#OutOfRange#sky##UAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall sky::OutOfRange::~OutOfRange(void)" (__imp_??1OutOfRange#sky##QAE#XZ) referenced in function _main
1>C:\Users\Matt\Documents\Game Development\DevEnv\SkyTest\Debug\SkyTest.exe : fatal error LNK1120: 3 unresolved externals
1>Done building project "SkyTest.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Edit:
I am using Visual Studio 2017 (could be the source of the error). The Client Project is using the .lib file.
An unresolved external is always a link error. It even has it in its name: LNK2019.
It is telling you it cannot find the implementation for sky::OutOfRange::OutOfRange()
You have it in a header somewhere and you've called it, but you have not linked to the library that implements it.
We have no way of telling you what library implements it or where it lives on your hard drive. You will have to consult the documentation for OutOfRange, the author of it, or yourself.
I can tell you that you will want to check:
right click the executable project->
properties->linker->general->additional library directories
properties->linker->input->additional dependencies
and make sure the path to the library that defines OutOfRange is in the former and the library name is in the latter.
EDIT: If the library itself has a header that imports it, as it appears from the code you posted, you just need to set up the additional directories part.
In the end, you have to consult the documentation for whatever library you are using or hit up their forums.
I am not sure but this may be related to your solution configuration and solution platform. It wasn't working for me, when I set my solution configuration to "Debug" and platform to "x64"; it started working after setting it to Release - x86
Related
I'm trying to perform some basic unit tests on a class that's in one project in a solution (Let's call it Project1) in another unit test project (Let's call it UnitTest1) in c++. I'm using the very latest version of visual studio 2019.
I created a brand new solution in visual studio 2019 for c++, and added a console application with a class HelloWorld in another file that just has a method to return a std::string "Hello World".
I then added a new "Native Unit Test Project" to the solution, under references added the Project1 console application, and typed the code as shown below:
The project1 file:
#include <iostream>
#include "HelloWorld.h"
int main() {
HelloWorld* hello = new HelloWorld();
std::cout << hello->sayHello();
}
HelloWorld.h:
#pragma once
#include <string>
class HelloWorld {
public: HelloWorld();
public: std::string sayHello();
};
HelloWorld.cpp:
#include "HelloWorld.h"
#include <string>
HelloWorld::HelloWorld() {
}
std::string HelloWorld::sayHello() {
return std::string("Hello World");
}
UnitTest1.cpp:
#include "pch.h"
#include "CppUnitTest.h"
#include "..//ConsoleApplication1/HelloWorld.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest1 {
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
HelloWorld* hello = new HelloWorld();
Assert::AreEqual(hello->sayHello(), std::string("Hello World"));
}
};
}
When i try to run the test via the test explorer, i get:
1>------ Build started: Project: UnitTest1, Configuration: Debug Win32 ------
1>pch.cpp
1>UnitTest1.cpp
1> Creating library C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.lib and object C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.exp
1>UnitTest1.obj : error LNK2019: unresolved external symbol "public: __thiscall HelloWorld::HelloWorld(void)" (??0HelloWorld##QAE#XZ) referenced in function "public: void __thiscall UnitTest1::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#1#QAEXXZ)
1>UnitTest1.obj : error LNK2019: unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall HelloWorld::sayHello(void)" (?sayHello#HelloWorld##QAE?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function "public: void __thiscall UnitTest1::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#1#QAEXXZ)
1>C:\Users\Iblob\source\repos\ConsoleApplication1\Debug\UnitTest1.dll : fatal error LNK1120: 2 unresolved externals
1>Done building project "UnitTest1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
I would have hoped that the linker should be able to find the files referenced according to microsofts own tutorial on this: https://learn.microsoft.com/en-us/visualstudio/test/writing-unit-tests-for-c-cpp?view=vs-2019
I've tried adding the classes header and cpp as an existing item to my unit test project, but then it just tries to find #include "pch.h" in the HelloWorld class when i try to run the tests.
What am i missing here to tell linker where to find the classes symbols?
Adding #include "..//ConsoleApplication1/HelloWorld.cpp" to my unitTest1.cpp file seems to have fixed things, although i'm not sure if this is an ideal solution, still, will mark as answer.
I normally work in c# and am out of my wits for this one . I used Walkthrough: Creating and Using a Dynamic Link Library (C++) to create a Dynamic Link Library.
I have defined two methods as shown below
DeveloperConsoleManager.h
#pragma once
#include "atlstr.h"
#ifdef DEVCONSOLEMANAGER_EXPORTS
#define DEVCONSOLEMANAGER_API __declspec(dllexport)
#else
#define DEVCONSOLEMANAGER_API __declspec(dllimport)
#endif
namespace DeveloperConsoleManager
{
class DeveloperConsoleLogic
{
public:
// Returns a + b
static DEVCONSOLEMANAGER_API double Add(double a, double b);
static DEVCONSOLEMANAGER_API bool CheckforValidFile(CString fileName);
};
}
DeveloperConsoleManager.cpp
// DeveloperConsoleManager.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "DeveloperConsoleManager.h"
namespace DeveloperConsoleManager
{
double DeveloperConsoleLogic::Add(double a, double b)
{
return a + b;
}
bool DeveloperConsoleLogic :: CheckforValidFile(CString fileName)
{
return false;
}
}
I use these methods in a .cpp file in a different project (type: Application (.exe)). When I Build the solution, there are following linker errors
Warning 1 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::Add' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 10
Warning 2 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 16
Error 3 error LNK2028: unresolved token (0A0004F1) "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 4 error LNK2019: unresolved external symbol "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 5 error LNK1120: 2 unresolved externals E:\MD_69\Debug\DeveloperConsoleUi.exe
There is no linker error for the "Add" method.
I have already included "DeveloperConsoleManager.lib" in Linker -> Input -> Additional Dependencies. Please help me find out what exactly am I doing wrong.
I would be glad to add any additional information needed.
Thanks to #Igor Tandetnik and the awesome thing that is internet, I figured it out. I am adding it as an answer so that some one else might benefit.
The problem was with CString. The project in which the function was defined was a dynamic link library (dll) and the call was being made from an MFC application. Now, the issue was that, MFC uses for CString while the non-MFC dll uses .
CString in is defined as:
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
while in is defined as:
typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CString;
This, as you can clearly see is different. The workaround I used was using CAtlString instead of CString . However, please feel free to suggest any better way if you come across.
I was trying to build "AccountDllTest.cpp" to test the dll "Account.dll" in Visual Studio 2013 but continuously getting this Linker Error ..
1>------ Build started: Project: AccountDllTest, Configuration: Debug x64 ------
1>AccountDllTest.obj : error LNK2019: unresolved external symbol "public: __cdecl Date::Date(int,int,int)" (??0Date##QEAA#HHH#Z) referenced in function main
1>AccountDllTest.obj : error LNK2019: unresolved external symbol "public: int __cdecl Date::getMonth(void)" (?getMonth#Date##QEAAHXZ) referenced in function main
1>C:\Users\Soumyadeep\Documents\Projects\AccountDllTest\x64\Debug\AccountDllTest.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The "Account.dll" was also successfully built with Visual Studio 2013 with the following files
Interface.h
Account.h
Date.h
Time.h
Account.cpp
Date.cpp
Time.cpp
Here the "Interface.h" just defines the abstract class "IAccount" containing pure virtual functions and the "Account.h" defines the "Account" Class derived from the "IAccount" class. The "IAccount" and "Account" classes are composed of objects of "Date" and "Time" classes defined and implemented in "Date.h","Date.cpp","Time.h","Time.cpp" respectively.
The code of AccountDllTest.cpp is given below
#include<iostream>
#include<conio.h>
#include"Headers\Interface.h"
#include<Windows.h>
using namespace std;
typedef IAccount* (_cdecl *FactoryFunc)();
int main()
{
HINSTANCE dll_handle = LoadLibrary(TEXT("..\\Core\\Account.dll"));
if (!dll_handle)
{
cout << "\n Unable to load Dll!!" << endl;
}
else
{
cout << "\n Dll successfully loaded!!" << endl;
}
FactoryFunc Create = (FactoryFunc)GetProcAddress(dll_handle, "createAccount");
IAccount* AC_1 = Create();
AC_1->setAccountNo(1);
AC_1->credit(2300);
cout << "\n Balance after credit" << AC_1->getBalance() << endl;
AC_1->lockAccount();
AC_1->credit(2300);
Date a;
a = AC_1->getLockDate();
cout<<"The account was locked on " ;
a.print();
_getch();
return 0;
}
The code was running without hiccups before I decided to test the Date objects after this line
AC_1->credit(2300);
What am I missing?
Sorry for this long question, but would really appreciate any help...
You must reference the DLL from your project.
To do this, simply:
In Solutions Explorer, click on your project and then, on the menu bar, click "Project" and next "References.
In "Common Properties", click "Framework and references" and next "Add new reference"
On the "Projects" tab, select your dll-project and click "OK".
Also you need to modify the includes directory path.
In Solutions Explorer, right click on your project and click "Properties"
In "C/C++" node (under "Configuration Properties"), select "General"
In "Additional Include Directories", add the path of the location of the headers (.h) of your DLL and click "OK"
You can read the official documentation for creating ad using a DLL.
https://msdn.microsoft.com/en-us/library/ms235636.aspx
Note that you have to add the defines on your header:
#ifdef YOURHEADER_EXPORTS
#define YOURHEADER_API __declspec(dllexport)
#else
#define YOURHEADER_API __declspec(dllimport)
#endif
If you use classes from your dll (as I see this is the Date class), first of all such classes must be imported with __declspec dllimport and secondly you have to link your test program with your dll library (yourdll.lib) to resolve external symbols:
AccountDllTest.obj : error LNK2019: unresolved external symbol "public: __cdecl Date::Date(int,int,int)" (??0Date##QEAA#HHH#Z) referenced in function main
AccountDllTest.obj : error LNK2019: unresolved external symbol "public: int __cdecl Date::getMonth(void)" (?getMonth#Date##QEAAHXZ) referenced in function main
Try to read about dllimport and dllexport here: https://msdn.microsoft.com/en-us/library/81h27t8c.aspx
I'm getting these error messages
2>main.obj : error LNK2019: unresolved external symbol "public: __thiscall CEngine::CEngine(void)" (??0CEngine##QAE#XZ) referenced in function _WinMain#16
2>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall CEngine::SetWindowSize(int,int,char const *,int)" (?SetWindowSize#CEngine##QAEXHHPBDH#Z) referenced in function _WinMain#16
2>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall CEngine::Begin(void)" (?Begin#CEngine##QAEXXZ) referenced in function _WinMain#16
2>main.obj : error LNK2019: unresolved external symbol "public: int __thiscall CEngine::GetDisplayWidth(void)" (?GetDisplayWidth#CEngine##QAEHXZ) referenced in function _WinMain#16
2>main.obj : error LNK2019: unresolved external symbol "public: int __thiscall CEngine::GetDisplayHeight(void)" (?GetDisplayHeight#CEngine##QAEHXZ) referenced in function _WinMain#16
2>C:\Users\ethan\Desktop\C++ Projects\delveenginetest\Debug\delveenginetest.exe : fatal error LNK1120: 5 unresolved externals
This is my solution:
Solution 'delveenginetest' (2 projects)
DelveEngine
Include
delve.h
Engine.h
SetupSDL.h
stdafx.h
Engine.cpp
Main.cpp
SetupSDL.cpp
This is the code for Engine.h
#pragma once
#include "SetupSDL.h"
class CEngine
{
public:
CEngine(void);
~CEngine(void);
void SetWindowSize(int winW, int winH, const char* GameName, int windowMode);
void Begin(void);
int GetDisplayWidth(void);
int GetDisplayHeight(void);
private:
int deskW;
int deskH;
bool playing;
CSetupSDL* sdl_setup;
};
Code for Engine.cpp
#include "Include/stdafx.h"
#include "Include/Engine.h"
CEngine::CEngine(void)
{
playing = true;
deskW = GetSystemMetrics(SM_CXSCREEN);
deskH = GetSystemMetrics(SM_CYSCREEN);
}
CEngine::~CEngine(void)
{
}
void CEngine::SetWindowSize(int winW, int winH, const char* GameName, int windowMode)
{
// set up SDL for use
sdl_setup = new CSetupSDL(winW, winH, GameName, windowMode);
}
void CEngine::Begin(void)
{
while (playing && sdl_setup->GetMainEvent()->type != SDL_QUIT)
{
sdl_setup->Begin();
sdl_setup->End();
}
playing = false;
}
int CEngine::GetDisplayWidth(void){ return deskW; }
int CEngine::GetDisplayHeight(void){ return deskH; }
The DelveEngine project builds successfully, whereas the delveenginetest project fails.
What's wrong? I've looked everywhere for a reason, can't find one that suits me.
Despite the fact you're not providing all the sufficient information for a correct diagnosis of your problems, I'll try to share what I could imagine that might be the reasons for the linker errors:
I suppose the project delveenginetest you mention is meant to set up unit tests for the classes from the DelveEngine project.
Since you have a Main.cpp in your DelveEngine project, I'd guess it's simply build as an executable (successfully).
Your delveenginetest needs to link to the classes provided from the DelveEngine project, but that's actually not possible, since the .exe from DelveEngine can't be used for linking, you'll need a library to import it to another executable (the unit testing framework).
I'd recommend to separate out your classes/source files from DelveEngine project to make up a static or shared library, that can be linked from an application and the test framework simultaneously from within a single VS solution:
Solution 'DelveEngine' (3 projects)
DelveEngineLib (project [.lib/.dll])
Include
delve.h
Engine.h
SetupSDL.h
Engine.cpp
SetupSDL.cpp
DelveEngine (project [.exe])
Main.cpp
delveenginetest (project [.exe])
Main.cpp (TestFramework main definition)
Since I'm not very versed with it I don't know actually, if VS 2013 supports to setup projects consuming virtual resources (think of links to sources in the actual build environment), but this could be an alternative how to setup application and unit tests without need of an extra library.
I have a visual c++ console project named "C_test".
Another project is called "dll_project" which is dll project.
in "C_test" project, I have set the location of additional include directory for "dll_project".
I have these simple codes.
in "C_test" project's main.cpp.
#include "SampleClass.h"
int main()
{
SampleClass *_parser = new SampleClass();
return 0;
}
And in "dll_project" SampleClass.h and SampleClass.cpp.
SampleClass.h
#pragma once
class SampleClass
{
public:
SampleClass(void);
~SampleClass(void);
};
SampleClass.cpp
#include "SampleClass.h"
SampleClass::SampleClass(void)
{
}
SampleClass::~SampleClass(void)
{
}
When I try to debug or build, I get this error.
error LNK2019: unresolved external symbol "public: __thiscall SampleClass::SampleClass(void)" (??0SampleClass##QAE#XZ) referenced in function _main C:\C_test\main.obj C_test
What have I done wrong?