Undefined reference when creating entry point in shared library clang - c++

I have an issue I don't understand. My project is quite simple for now. I have a shared library Engine which is called by my executable. I'm trying to move the entry point inside my shared library, so the executable part only has functions and some class to create.
---EDIT: I edit to post the project as it is reproductible easily.
To do so, I have these files in my shared library:
entry.h
BaseGame.h
Application.cpp
Here is entry.h
#include "BaseGame.h"
extern game* create_game();
int main(int argc, char *argv[])
{
auto testgame = create_game();
delete testgame;
return 0;
}
BaseGame.h
class __declspec(dllexport) game
{
public:
game() = default;
virtual ~game();
virtual bool initialize() =0;
virtual bool update(float deltaTime) =0;
virtual bool render(float deltaTime) =0;
virtual void on_resize() =0;
};
Application.cpp
#include "BaseGame.h"
class __declspec(dllexport) Application
{
public:
Application()=default;
~Application()=default;
};
And in my executable, I have two files entry.cpp which defines create_game and my_game.h which inherited from game.
entry.cpp
#include <entry.h>
#include "my_game.h"
game* create_game()
{
return new myGame;
}
and my_game.h:
class myGame : public game
{
public:
myGame(){};
~myGame() override = default;
bool initialize() override;
bool update(float deltaTime) override;
bool render(float deltaTime) override;
void on_resize() override;
};
my_game.cpp:
#include "my_game.h"
bool myGame::initialize()
{
return true;
}
bool myGame::update(float deltaTime)
{
return true;
}
bool myGame::render(float deltaTime)
{
return true;
}
void myGame::on_resize()
{
}
What I don't understand is that I always get an linker error when building my exe:
Création de la bibliothèque ..\bin\testbed.lib et de l'objet ..\bin\testbed.exp
entry-3b33f2.o : error LNK2019: symbole externe non résolu "public: virtual __cdecl game::~game(void)" (??1game##UEAA#XZ) référencé dans la fonction "public: virtual __cdecl myGame::~myGame(void)" (??1myGame##UEAA#XZ)
..\bin\testbed.exe : fatal error LNK1120: 1 externes non résolus
Also here is how i build my shared library:
SET assembly=Engine
SET compilerFlags=-g -shared -Wvarargs -Wall -Werror
SET includeFlags=-Isrc
SET linkerFlags=-luser32
SET defines=-D_DEBUG_EG -DGEXPORT -D_CRT_SECURE_NO_WARNINGS
ECHO "Building %assembly%%..."
clang++ %cFilenames% %compilerFlags% -o ../bin/%assembly%.dll %defines% %includeFlags% %linkerFlags%
And here is my executable:
SET assembly=testbed
SET compilerFlags=-g
REM -Wall -Werror
SET includeFlags=-Isrc -I../Engine/src/
SET linkerFlags=-L../bin/ -lEngine.lib
SET defines=-D_DEBUG_EG -DGIMPORT
clang++ %cFilenames% %compilerFlags% -o ../bin/%assembly%.exe %defines% %includeFlags% %linkerFlags%
Even if game is exported. Does anyone see something wrong? PS: I'm using Clang as the compiler.

The game class lacks a destructor definition. I suggest making it default:
class myGame : public game
{
public:
myGame(){};
~myGame() override = default; // here
bool initialize() override;
bool update(float deltaTime) override;
bool render(float deltaTime) override;
void on_resize() override;
};
You may also remove the default constructor and destructor from myGame. It'll be default constructible and have a virtual destructor by default.
class myGame : public game
{
public:
// myGame(){}; // remove
// ~myGame() override = default; // remove
// ...
Other notes:
All your header files should have header guards to prevent including the same file twice in one translation unit.
my_game.h should #include "BaseGame.h" to get the definition of game.

You example is not entirely complete. I assume the destructor ~game() is actually defined in some cpp file of the shared library. And my_game.h needs to include BaseGame.h (since myGame derives from game). So basically my_game.cpp in the executable ends up seeing the definition of game as shown, including the __declspec(dllexport). However, the executable should not see __declspec(dllexport) (i.e. the exe should not export game) but rather it should see __declspec(dllimport) (i.e. the exe should import game). So you want to define game with __declspec(dllexport) while building the dll and __declspec(dllimport) while building the executable.
The typical way to conditionally have one or the other is by using a macro and changing its definition based on a preprocessor symbol which is different for the exe and the dll. For example (adapted from the official documentation):
// Either in BaseGame.h or in a dedicated header
// that gets included by BaseGame.h.
#ifdef EXPORT_GAME_SYMBOLS
#define GAME_DECLSPEC __declspec(dllexport)
#else
#define GAME_DECLSPEC __declspec(dllimport)
#endif
// BaseGame.h
class GAME_DECLSPEC game
{ ... class definition ... };
While building the dll, you do define EXPORT_GAME_SYMBOLS in the preprocessor (-DEXPORT_GAME_SYMBOLS). But while building the executable, you do not define EXPORT_GAME_SYMBOLS.
The linker complains only about the destructor of game because only the destructor has a non-inline implementation in your example. The default constructor is inline (game() = default;, meaning that an export is not necessary for the linker to find an implementation) and the other functions are pure (meaning that they do not have an implementation to begin with).
Hence, an alternative here would be to completely remove the export/import stuff from game and define the destructor inline, too (virtual ~game() = default;).
But of course, if everything is inline, you do not need to build a shared library to begin with...
Side notes:
The __declspec(dllexport) on Application makes no sense since it is in a .cpp file of the dll, meaning that code in the executable can never see the definition of Application. (Except if you #include "Application.cpp", which you shouldn't.) So no need to export the symbol.
As others have noted, having the main() in the header file is uncommon. You could move it e.g. to my_game.cpp or a dedicated main.cpp in your exe project.

Related

How to define the function out side the Library?

we have some dynamic plugin-dll, which is generated through separate protect, and use while the software is start. Plugin-dll code is use some of header file from main project. while compiling plugin code, If main project header file contain some function, and definition outside the class, at that time I am getting error like unresolved external symbol.
This error are expected because of plugin code does not find the definition of (main project) function.
Note: plugin must be compile before compilation of main project.
In two situation plug in code is compile.
1) If main project header file has pure virtual function then it is work
perfectly (plug code is compile fine).
2) If I will write the function definition inside the class.
I tried inline function but it is did not work.
---------------------
*** Main Project ***
---------------------
->This project generate .exe file
mainProject.h
-------------
class MainProjectHeder{
virtual void foo() = 0; // this function is work
void foo1(); // this function giving me error like unresolved external symbol
void foo2{ // this work
print("hello");
};
};
void MainProjectHeder::foo1(){
print("function not working");
}
ExperimentFactoryInterface.h
----------------------------
#include <MainProjectHeder.h>
class ExperimentFactoryInterface {
public:
virtual ~ExperimentFactoryInterface() {}
virtual MainProjectHeder* CreateExperiment(const QVariant& = QVariant()) = 0;
};
----------------------
*** Pulgin code ***
----------------------
->This Project is generate DLL file
Experiment.h
-------------
#include <mainProject.h>
class Experiment : public MainProjectHeder{
virtual void foo();
};
void Experiment:foo(){
print("work fine");
}
Factory.h
----------
#include "cyclicvoltammetry.h"
#include <ExperimentFactoryInterface.h>
class Factory : public ExperimentFactoryInterface {
public:
MainProjectHeder* CreateExperiment(const QVariant& = QVariant());
};
MainProjectHeder* Factory::CreateExperiment(const QVariant&) {
return new Experiment;
}
while compiling code of plugIn; how can I inform to compiler like definition of function void foo1(); is write out side the project or in another project?
A member function of a class is a function that has its definition or its prototype within the class definition like any other variable. It operates on any object of the class of which it is a member, and has access to all the members of a class for that object.

Non-exported virtual function results in LNK2001 in derived classes in other projects

I discovered this little gotcha with virtual functions and DLLs, and thought I would share what I learned about it.
Let's say that you have two projects, called Alpha and Bravo. Alpha is built as a DLL, to which Bravo references. Now, in Alpha, you have the base class:
Header file: (Alpha.h)
#pragma once
#if defined(EXPORT_ALPHA)
#define ALPHA_API __declspec(dllexport)
#else
#define ALPHA_API __declspec(dllimport)
#endif
class BaseClass
{
public:
ALPHA_API BaseClass();
ALPHA_API virtual ~BaseClass();
virtual void Foo();
};
Cpp file: (Alpha.cpp)
#include "Alpha.h"
#include <cstdio>
BaseClass::BaseClass() {}
BaseClass::~BaseClass() {}
void BaseClass::Foo()
{
printf( "Foo\n" );
}
Then, in Bravo, you have the derived class and main (call it main.cpp):
#include "Alpha.h"
#include <cstdio>
class DerivedClass : public BaseClass
{
public:
DerivedClass() : BaseClass() {}
virtual ~DerivedClass() {}
};
int main()
{
DerivedClass* derived = new DerivedClass();
printf( "Created instance of derived class.\n" );
delete derived;
return 0;
}
Now, Alpha builds successfully, generates its DLL, and goes on its merry way. But then, you go to build Bravo, and you get LNK2001 - unresolved external symbol BaseClass::Foo(), even if you never actually use it.
So, what is happening? Why is it generating a linker error if we never call Foo()?
It is due to how the virtual table is populated by the linker. When you are linking Alpha, it has both the declaration of the virtual function, and since it knows where the assembled code for Foo() is, it just populates the BaseClass's virtual table with the address of the assembled code. But, since Foo() is not exported, it doesn't add an entry for the function to the corresponding lib. So, for instance, if a DLL and static lib were compiled with comments, they might look something like this:
Alpha.dll:
# this is BaseClass's virtual table, located at some random address only known internally
0x00002000 # Function address of ~BaseClass()
0x00004000 # Function address of Foo()
# This is the machine code for Foo(), located at address 0x00004000
mov eax, [ebx]
add eax, ecx
...
Alpha.lib:
# Exports:
BaseClass()#BaseClass : 0x00001000 # Address in the DLL of the constructor
~BaseClass()#BaseClass : 0x00002000 # Address in the DLL of the destructor
When it goes to link Bravo, it knows that it needs to add an entry for Foo() to DerivedClass's virtual table. (It knows because the compiler told it when it read the included headers.) So, first, the linker looks for a compiled function called Foo()#DerivedClass. There isn't one, so then it looks for a compiled function called Foo()#BaseClass. However, the static lib does not have an entry for Foo()#BaseClass, because Alpha did not export it. Thus, the linker doesn't find any entries for Foo()#BaseClass, and therefore cannot populate DerivedClass's virtual table with a function address for Foo().
This means that you will get the linker error in the downstream project. It also means that if DerivedClass provides an implementation for Foo(), this linker error will not occur unless that implementation attempts to call the base class's implementation. However, the right way to fix this is to make sure you export all virtual functions in a class that might have derived classes in downstream projects (either that, or export the class itself).

ld: duplicate symbols for architecture x86_64 when defining a global var in a header

How to solve this problem?
Just getting following errors:
g++ output:
duplicate symbol _game in:
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/main-62666f.o
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/Game-a5a31d.o
duplicate symbol _game in:
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/main-62666f.o
/var/folders/w6/yqp0s0t92hl5g842hg8tztfr0000gn/T/Write-83f8ee.o
It seems like the problem is not in the header files.
EDIT: Header files look like this:
#ifndef GAME_H
#define GAME_H
#include "Color.h"
#include "Tile.h"
class Game
{
public:
Game();
~Game();
Color getActivePlayer();
void setStarttile(Tile Firststarttile);
Color togglePlayer();
void setRunning(bool run);
char newActiveplayer;
void run();
void runsecondmethod();
private:
Game(const Game &);
Color Activeplayer;
Tile *Starttile;
bool Running;
}game;
#endif
You have instantiated a Game instance in your header file "Game.h", and since this is being included in multiple files you end up with multiple instances of game at link time. Change:
class Game
{
public:
...
}game;
to:
class Game
{
public:
...
};
extern Game game;
and then add:
Game game;
in one of your .cpp files.
In your header file (the one included from Write.cpp and GameBoard.cpp), you're likely to have an instantiation instead of a declaration.
Common cases/pitfalls :
missing extern before global variables
having function implementation (i.e. having void foo(Bar& b) {} instead of void foo(Bar& b);
Without more details, hard to help...
Look for where addnewtile function is defined for example...
EDIT
With more details
class Game
{
(zip)
}game;
This is declaring the class Game and creating a game object each time you include the header file.
Use
class Game
{
(zip)
};
In the header file and Game game; in the cpp
Or use a singleton pattern / static instance.

What C++ compiler/linker does when using runtime DLL loading?

I would like to understand the DLL mechanism and what the compiler does when I loads the DLL at run-time (i.e. I will not use the generated .lib).
Consider the following C++ code:
DLL interface header file
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API Base
{
public:
Base();
virtual ~Base();
virtual int get_number() const;
virtual const char* what() const = 0;
private:
int i_;
};
class MYDLL_API Child : public Base
{
public:
Child();
virtual ~Child();
virtual int get_number() const override;
virtual const char* what() const override;
private:
int j_;
};
extern "C" {
MYDLL_API Base* __cdecl initializeObject();
}
DLL implementation source file
#include "MyDLL.hh"
Base::Base()
: i_(42)
{}
Base::~Base()
{}
int Base::get_number() const
{
return i_;
}
Child::Child()
: Base()
, j_(24)
{}
Child::~Child()
{}
int Child::get_number() const
{
return j_;
}
const char* Child::what() const
{
return "Hello!";
}
Base* initializeObject()
{
return new Child();
}
The goal of this DLL is to have a common interface defined by the Base class, but it allows specifics implementations compiled in different DLLs that are loaded at runtime (here the Child class is exposed for the purpose of the example).
At this stage, if I naively include the DLL's header:
#include "MyDLL.hh"
int main()
{
Base* b = new Child();
std::cout << b->get_number() << std::endl;
std::cout << b->what() << std::endl;
delete b;
getchar();
return 0;
}
The linker complains LNK2019 and LNK2001 errors: it can not resolves symbols. So, it behaves as expected (I did not use the .lib).
Consider now, the following code that I use to load the DLL at runtime:
#include "MyDLL.hh"
typedef Base* (*initFuncType)();
int main()
{
HINSTANCE handle = LoadLibrary(L"MyDLL.dll");
initFuncType init = nullptr;
init = (initFuncType)(GetProcAddress(handle, "initializeObject"));
if (init)
{
Base* b = init(); //< Use init() !
std::cout << b->get_number() << std::endl;
std::cout << b->what() << std::endl;
delete b;
}
getchar();
FreeLibrary(handle);
return 0;
}
This time it works, the linkage is done.
1st question: What happened? What changed for the compiler and the linker? The use of the function pointer on initializeObject() solves the problem.
The other issue I do not understand well is when I remove virtual and override of get_number():
int get_number() const;
I have a LNK2019 error because of the unresolved Base::get_number(void) const symbol in the _main function. I understand that the virtual keyword will resolve the member function dynamically (at run-time). In our case, the DLL is not loaded yet, the get_number symbol is not available.
2nd question: Does this means that methods must always be virtual using DLL run-time linking?
3rd question: How can I have the C++ function exportation with the Windows API? So that I could remove the extern "C" { ... } stuff.
Thanks for your reading! I hope I will read interesting answers! :)
There are two ways to link dll files.
The 2nd way (the way it works) is the C Binding approach, where you query the dll for a specific function name and it returns a functor to you.
Using the 2nd way you won't be able to extend the base classes, since they are not defined (you don't have any code to be copy pasted so to speak at linkage time).
In order to have a dll who's classes can be extended, you will need to use dynamic binding. You need to compile your .dll and also provide a Symbols Library (or an export library). You have this option in VS studio in project properties.
The mechanism is as following :
Compile Dll project -> output : myLib.dll , myLib.lib
Use exported symbols from myLib.lib inside your main project (main project takes myLib.lib as dependency)
at runtime,due to the binding, your program will know it requires myLib.dll to work so it will load it (if found, else you get runtime error)
Another advantage of using Export Library is that you can export C++ functions (which are mangled on export).
It's very hard to have C Binding on mangled functions.
C Binding on the otherhand, compared to the dynamic binding, won't make your program scream if myLib.dll isn't found , you will just get a null pointer to function.

Overloading default constructor causing error [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
I've been developing C# and Java (among many other languages) for many years, and I'm just now getting my feet wet in C++. I've buried myself in resources on inheritance and classes, but I just can't seem to figure out how to get rid of this pesky error.
My code:
Entity.h:
#ifndef ENTITY_H
#define ENTITY_H
#include <iostream>
class Entity
{
public:
std::string m_name;
void update(float delta);
Entity();
private:
virtual void step(float delta);
};
#endif
Entity.cpp:
#include "Entity.h"
Entity::Entity()
{
m_name = "Generic Entity";
}
void Entity::update(float delta)
{
step(delta);
}
void Entity::step(float delta) {}
Player.h:
#ifndef PLAYER_H
#define PLAYER_H
#include "Entity.h"
class Player : public Entity
{
public:
Player();
private:
virtual void step(float delta);
virtual void draw() const;
};
#endif
Player.cpp:
#include "Player.h"
Player::Player()
{
m_name = "Player";
}
void Player::step(float delta) {}
void Player::draw() const {}
Main.cpp:
int main()
{
return 0;
}
As you can see, I'm not doing anything with the classes, but I'm getting these errors:
Error 3 error LNK1120: 1 unresolved externals C:\[...]\Debug\ConsoleApplication1.exe ConsoleApplication11
Error 2 error LNK2019: unresolved external symbol "public: __thiscall Entity::Entity(void)" (??0Entity##QAE#XZ) referenced in function "public: __thiscall Player::Player(void)" (??0Player##QAE#XZ) C:\[...]\ConsoleApplication1\Player.obj ConsoleApplication1
UPDATE: The code magically works when I comment out the following code in Player.cpp:
/*Player::Player()
{
m_name = "Player";
}*/
It looks like Entity isn't linked to player. Make sure output shows it compiling and that they are both added to your project
You also need to define a virtual destructor in your base class
Edit:
It doesn't have to compile first, my mistake. In C/C++, program creation is in two steps. First the compiler creates obj files for your cpp files, such as Entity.obj, Player.obj and so on. Then the linker will bundle everything together.
In Player.cpp, you say that you will have a class named Entity at some point, so the compiler finds the definition of that class in the .h file. Player.cpp then gets transformed into executable code in Player.obj but it won't contain the Entity.obj executable code. The compilation step works.
Then the linker will try to parse Player.obj and find Entity.obj that the compiler said will exists. If it doesn't then you get the "undefined reference" error, because the definitions found do not match the actual executable.
The virtual destructor is mandatory. The way inheritance works in C++ is with the virtual table. For each class with inheritance, a virtual table (vtable) is created with the virtual entries. When the linking step is performed, the linker will fill the vtable with the actual function. When the code executes, it checks the vtable for that class then execute that function. This allows you to "override" base methods or use the base method if nothing new is added. The virtual destructor creates the entry in that table for the destructor. If there is no entry for a virtual destructor, then the child class will not have an entry and won't be able to destroy the base class properly, which results in undefined behavior