LNK2019 on a solution with a dll project - c++

I am trying to create a solution which one project is the .exe and the other project is a simple dll. What i am trying to learn is how to link between two projects. I have searched stack-overflow and found really nice answers which I have followed, such as declaring the right header bath on:
Properties->Configuration Properties->C/C++->General->Additional Include Directories
Then setting the .lib on:
Properties->Configuration Properties->Linker->Input->Additional Dependencies
I used macros to generate that .lib file also. Here is the my simplified code:
The .exe:
cpp:
#include "stdafx.h"
#include "../ConsoleApplication2/HelloWorld.h"
int _tmain(int argc, _TCHAR* argv[])
{
hello_world hw;
hw.printHello();
getchar();
return 0;
}
The dll:
header:
#pragma once
#ifdef is_hello_world_dll
#define hello_world_exp __declspec(dllexport)
#else
#define hello_world_exp __declspec(dllimport)
#endif
class hello_world_exp hello_world
{
public:
hello_world();
~hello_world();
void printHello();
};
cpp:
#include "stdafx.h"
#include "HelloWorld.h"
#include <iostream>
hello_world::hello_world()
{
}
hello_world::~hello_world()
{
}
void printHello()
{
std::cout << "Hello World" << std::endl;
}
A note: The solution compiles fine when I don't call hw.printHello(); however when I do call it, the linker generates :
Error 1 error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __thiscall hello_world::printHello(void)" (__imp_?printHello#hello_world##QAEXXZ) referenced in function _wmain C:\Users\usteinfeld\Desktop\Private\Students\Yana\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.obj ConsoleApplication1

This function is defined as a free function based on how you wrote it
void printHello()
It belongs to the class hello_world so you should scope it as such
void hello_world::printHello()
{
std::cout << "Hello World" << std::endl;
}

Related

C++ DLL import class unresolved external symbol

Hi I'm sorry I've seen that there is a lot of "unresolved external symbol error" questions, and I've seen them but none of the answers that I found fixed my error.
I've tested 2 ways to compile the DLL and use the HelloWorld method from SerialPort class.
btw I'm using VS2019 community edition
Both ways are throwing the same error :
Error LNK2019 unresolved external symbol "public: void __thiscall SerialPort::HelloWorld(void)" (?HelloWorld#SerialPort##QAEXXZ) referenced in function _main Test DriverCore C:\Users\$USER\source\repos\Test DriverCore\Test DriverCore\Main.obj 1
To what I've understood it's a linker error and the name of the method that I'm using is unresolved (not found) but I have no idea how to fix that (I thought that extern "C" prevented this to happen)
I've also tried to add #pragma comment(lib, "DriverCore.lib")(with DriverCore.lib in the same Dir as DriverCore.h) but still nothing :/
Way 1
using a function to return a pointer to the class
DriverCore.h
#pragma once
#ifdef DRIVERCORE_EXPORTS
#define DLLCALL __declspec(dllexport)
#else
#define DLLCALL __declspec(dllimport)
#endif
class SerialPort
{
private:
bool connected = 0;
public:
SerialPort() {};
void HelloWorld();
bool isConnected() { return 0; };
int readSerialPort(char* buffer, unsigned int buf_size) { return 0; };
bool writeSerialPort(char* buffer, unsigned int buf_size) { return 0; };
};
extern "C" {
DLLCALL SerialPort* __stdcall CreateSerialPort();
};
DriverCore.cpp
#include "pch.h"
#include "DriverCore.h"
#include <iostream>
#define DRIVERCORE_EXPORTS
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
SerialPort* __stdcall CreateSerialPort()
{
return new SerialPort();
}
void SerialPort::HelloWorld()
{
std::cout << "Hello World !";
}
Main.cpp
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include "DriverCore.h"
typedef SerialPort* (__stdcall *SerialPortImported) ();
int main()
{
// instantiate the dll location
HINSTANCE hDLL = LoadLibraryW(L"DriverCore.dll");
if (!hDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
//Resolve Objects Addr
SerialPortImported pCSerialPort = (SerialPortImported) GetProcAddress(hDLL, "CreateSerialPort") ;
SerialPort* CSerialPort = pCSerialPort();
CSerialPort->HelloWorld();
return 0;
}
Way 2
without using extern "c" {...} but using __declspec directly onto the class declaration
DriverCore.h
#pragma once
#ifdef DRIVERCORE_EXPORTS
#define DLLCALL __declspec(dllexport)
#else
#define DLLCALL __declspec(dllimport)
#endif
class DLLCALL SerialPort
{
private:
bool connected = 0;
public:
SerialPort() {};
void HelloWorld();
bool isConnected() { return 0; };
int readSerialPort(char* buffer, unsigned int buf_size) { return 0; };
bool writeSerialPort(char* buffer, unsigned int buf_size) { return 0; };
};
DriverCore.cpp
#include "pch.h"
#include "DriverCore.h"
#include <iostream>
#define DRIVERCORE_EXPORTS
BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
return TRUE;
}
void SerialPort::HelloWorld()
{
std::cout << "Hello World !";
}
Main.cpp
#include "pch.h"
#include <Windows.h>
#include <iostream>
#include "DriverCore.h"
int main()
{
// instantiate the dll location
HINSTANCE hDLL = LoadLibraryW(L"DriverCore.dll");
if (!hDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return EXIT_FAILURE;
}
//Resolve Objects Addr
SerialPort* pSerialPort = (SerialPort*) GetProcAddress(hDLL, "SerialPort") ;
pSerialPort->HelloWorld();
return 0;
}
Thanks a lot in advance for your help !
You are calling HelloWorld which is missing its implementation in your application.
There is some fundamental misunderstanding about how C++ executables are compiled and linked against DLLs.
No libraries:
All symbols that the Application needs must be defined in the Application.
All needed symbol definitions must be available to the linker.
Static libraries:
All symbols that the Application needs must be defined in the Application or a static library.
All needed symbol definitions must be available to the linker.
The symbols are added to the generated Application's executable.
Dynamic libraries:
All symbols that the Application needs must be defined in the Application or a dynamiclibrary.
All needed symbol definitions must be available to the linker.
The symbols remain at their original places and they are loaded only at load time. This allows swap the dynamic libraries with any other ABI-compatible one at load time.
Since you are not linking with the dll and only load it at runtime, the linker correctly complains about the missing HelloWorld method.
Extern "C" is irrelevant here.

Linker issue in Visual Studio C++

I'm trying to get started with C++ in VS 2017 (empty project template), but immediately ran into linker problems when adding 1 simple class, so I guess I'm missing something important...
My project looks like this:
test.h:
#include <iostream>
class test
{
public:
test();
~test();
std::string getInfo();
};
test.cpp:
#include "test.h"
test::test() {}
test::~test() {}
std::string getInfo() {
return "test";
}
And main.cpp:
#include <iostream>
#include <string>
#include "test.h"
int main(int argc, char **argv) {
test t;
std::cout << "output: " << t.getInfo() << std::endl;
return 0;
}
The linker error I get is the infamous LNK2019:
LNK2019 unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl test::getInfo(void)" (?getInfo#test##QEAA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function main
Any ideas what I am doing wrong here?
Thanks!
In file test.cpp you need to properly specify the scope of the member function:
std::string test::getInfo() {
return "test";
}
Note the test:: before the getInfo()

How do I avoid `already defined` linking error with pugixml if two static libs contain pugixml objs?

So I have 2 static libs defined like this:
StaticLib1
// StaticLib1.h
#pragma once
class StaticLib1
{
public:
void doSomething1();
};
cpp:
// StaticLib1.cpp
#include "pugixml.hpp"
#include "StaticLib1.h"
void StaticLib1::doSomething1()
{
pugi::xml_node node;
}
StaticLib2
// StaticLib2.h
#pragma once
class StaticLib2
{
public:
void doSomething2();
};
cpp:
// StaticLib1.cpp
#include "pugixml.hpp"
#include "StaticLib2.h"
void StaticLib2::doSomething2()
{
pugi::xml_node node;
}
Main
#include <iostream>
#include "StaticLib1.h"
#include "StaticLib2.h"
int main(int argv, char** argc)
{
StaticLib1 staticlib1;
StaticLib2 staticlib2;
staticlib1.doSemething1();
staticlib2.doSemething2();
getchar();
return 0;
}
Now, if I build this. I get a lot of linking errors. Here are the first few linking errors:
3>StaticLib2.lib(StaticLib2.obj) : error LNK2005: "public: __thiscall pugi::xml_attribute::xml_attribute(struct pugi::xml_attribute_struct *)" (??0xml_attribute#pugi##QAE#PAUxml_attribute_struct#1##Z) already defined in StaticLib1.lib(StaticLib1.obj)
3>StaticLib2.lib(StaticLib2.obj) : error LNK2005: "public: __thiscall pugi::xml_attribute::xml_attribute(void)" (??0xml_attribute#pugi##QAE#XZ) already defined in StaticLib1.lib(StaticLib1.obj)
3>StaticLib2.lib(StaticLib2.obj) : error LNK2005: "private: __thiscall pugi::xml_attribute_iterator::xml_attribute_iterator(struct pugi::xml_attribute_struct *,struct pugi::xml_node_struct *)" (??0xml_attribute_iterator#pugi##AAE#PAUxml_attribute_struct#1#PAUxml_node_struct#1##Z) already defined in StaticLib1.lib(StaticLib1.obj)
...
...
Now, I understand that this linking error is because there is a pugixml.obj inside StaticLib1.lib, and there is pugixml.obj inside StaticLib2.lib. But I don't understand why this would cause linking error with pugixml signatures. Why would they be defined twice? If I call staticlib1.doSomething1() shouldn't main not care if there are multiple definitions of pugi? Shouldn't staticlib1.doSomething1() handle all of that?
on the pugiconfig.hpp I have these specific settings:
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
#define PUGIXML_WCHAR_MODE
#define PUGIXML_HEAD_ONLY
#include "pugixml.cpp"
#endif
So yes, from user0042advice, I realize it is better to compile a pugixml.lib on your own rather than having #include "pugixml.cpp" on the config. I'm working with legacy code so these surprises are there. Now, I've fixed my issue and made my company code slightly cleaner.

Static Lib using namespace leads to unresolved external

I am using VS2013 and I have a static lib project with the following header:
#pragma once
namespace StaticLibNamespace
{
void foo( void );
}
Then the function is defined in the cpp as follows:
#include "stdafx.h"
#include "StaticLibHeader.h"
using namespace StaticLibNamespace;
void foo( void )
{
;
}
In my simple console app, I include the reference to StaticLibNameSpaceTest.lib and my main function is the following:
#include "stdafx.h"
#include "..\StaticLibNamespaceTest\StaticLibHeader.h"
int _tmain(int argc, _TCHAR* argv[])
{
StaticLibNamespace::foo();
return 0;
}
If I try and compile this I get the following error:
NamespaceTest.obj : error LNK2019: unresolved external symbol "void __cdecl StaticLibNamespace::foo(void)" (?foo#StaticLibNamespace##YAXXZ) referenced in function _wmain
However if I change my static lib cpp file to the following everything is fine:
#include "stdafx.h"
#include "StaticLibHeader.h"
void StaticLibNamespace::foo( void )
{
;
}
I'm obviously not understanding everything going on with "using namespace" can someone please enlighten me? Thanks!
The using namespace directive changes the lookup rules for symbols when the compiler sees an unqualified name and needs to find what it refers to.
However, in your case, you are defining a new function called foo. As an unqualified name, this defines a new foo in the global namespace (assuming there wasn't already one there). When you qualify the name, you are defining StaticLibNamespace::foo as you intend.
A different solution might be:
namespace StaticLibNamespace {
void foo( void )
{
;
}
} // namespace StaticLibNamespace

C++ DLL linker error

I want to write a dll for an api of a device. since i am new to dlls i wanted to implement it on a simple text editor and then make one for the api.
I have made header file and cpp file but when i run the code i get error lnk2001 followed by lnk1120 which is unresolved external error.
I really have no idea where did i make a mistake, as far as i see i did it the right way. i was wondering if you guys could help me out. tnx.
here is my header file
// EditFuncsDll.h
#include <cstdio>
#include <vector>
#include <string>
namespace EditFuncs
{
class MyEditFuncs
{
private:
static std::vector<std::string> MyTextBox;
public:
static __declspec(dllexport) void Load(std::string command);
static __declspec(dllexport) void Save(std::string command);
static __declspec(dllexport) int Lines();
static __declspec(dllexport) void Add(std::string command);
static __declspec(dllexport) void Remove(std::string command);
static __declspec(dllexport) void Insert(std::string command);
static __declspec(dllexport) int wc(std::string command);
static __declspec(dllexport) void GetInfo();
};
}
and in my cpp file i just define the functions i declared in header file.
and these are the errors i get
Error 25 error LNK2001: unresolved external symbol "private: static class std::vector,class std::allocator >,class std::allocator,class std::allocator > > > EditFuncs::MyEditFuncs::MyTextBox" (?MyTextBox#MyEditFuncs#EditFuncs##0V?$vector#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V?$allocator#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###2##std##A) C:\Users\Lucy\Desktop\Erfan\Text_Editor_DLL\Text_Editor_DLL\EditFuncsDll.obj Text_Editor_DLL
and
Error 26 error LNK1120: 1 unresolved externals C:\Users\Lucy\Desktop\Erfan\Text_Editor_DLL\Debug\Text_Editor_DLL.dll Text_Editor_DLL
The head of your cpp should be like this :
#include "EditFuncsDll.h"
#include <iostream>
#include <fstream>
using namespace std;
namespace EditFuncs
{
std::vector<std::string> EditFuncs::MyEditFuncs::MyTextBox;
void MyEditFuncs::Load(string command)
{
string filename; // The name of the file starts at the fifth character of the command and goes to the end
filename = command.substr(5,command.size());
ifstream inFile;
inFile.open(filename);
.
.
.
In your DLL's header file you may want to use a preprocessor macro, that expands to __declspec(dllimport) for DLL clients, and to __declspec(dllexport) for code that is implementing the DLL (i.e. your DLL .cpp files).
// EditFuncsDll.h
#ifdef EDIT_FUNCS_DLL_IMPLEMENTATION
#define EDIT_FUNCS_DLL __declspec(dllexport) // for DLL implementation
#else
#define EDIT_FUNCS_DLL __declspec(dllimport) // for clients
#endif
class EDIT_FUNCS_DLL MyEditFuncs
{
...
};
In your DLL's source .cpp file(s), you can #define EDIT_FUNCS_DLL_IMPLEMENTATION before #including your DLL header:
// EditFuncsDll.cpp
#define EDIT_FUNCS_DLL_IMPLEMENTATION
#include "EditFuncsDll.h"
// ... implementation code