Considering it's a common issue, what could be the source of this error if one uses this file logic:
Utils.h: declare bool Dummy();
Utils.cpp: define bool Dummy() {return true;}
ClassA.h : an irrelevant class A { bool sheet; public: A(); };
ClassA.cpp: the irrelevant code:
#include "Utils.h"
#include "ClassA.h"
A::A() { sheet = Dummy(); }
Note: all header files contain the guard #pragma once macro.
The error: something like this
Error 2 error LNK2028: unresolved token (0A00000B) "bool __clrcall Dummy(void)"
Error 3 error LNK2019: unresolved external symbol "bool __clrcall Dummy(void)" .... in ClassA.obj
bool __clrcall Dummy(void)
You are compiling the ClassA.cpp file with /clr in effect, generating managed code. Your Dummy() function however was compiled without /clr, making the calling convention __cdecl. The linker notices the discrepancy, it can't find the managed implementation for Dummy.
You must tell the compiler that Utils.cpp was built to native code. Fix ClassA.cpp like this:
#pragma managed(push, off)
#include "Utils.h"
#pragma managed(pop)
#include "ClassA.h"
// etc...
Related
I have a Visual C++ solution, using Visual Studio 2017, which contains 5 projects:
SpikeConfig
SpikeEngine
SpikeRenderer
SpikeUI
SpikeUtils
In SpikeUtils, I have a header _SpikeEngineObject.h:
#pragma once
#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif
#include "GUID.h"
namespace SpikeUtils
{
class SPIKEUTILS_EXPORT _SpikeEngineObject
{
public:
const std::string & _SpikeEngineId()
{
return _SpikeRef.Value();
}
private:
SpikeUtils::GUID _SpikeRef = SpikeUtils::GUID::Generate();
};
}
The file GUID.h included looks like this:
#pragma once
#include <iostream>
#ifdef DLL_SPIKEUTILS
#define SPIKEUTILS_EXPORT __declspec(dllexport)
#else
#define SPIKEUTILS_EXPORT __declspec(dllimport)
#endif
namespace SpikeUtils
{
class SPIKEUTILS_EXPORT GUID final
{
public:
GUID(GUID const & other) = default;
GUID& operator=(GUID& other) = default;
static GUID Generate();
std::string const & Value();
private:
GUID(std::string const & value) : value(value)
{}
std::string value;
};
}
I am omitting the implementation of GUID.cpp because I don't think it's relevant.
Now, in SpikeUI, I have a class Drawable, that just inherits from _SpikeEngineObject.h
#pragma once
#include "_SpikeEngineObject.h"
#ifdef DLL_SPIKEUI
#define SPIKEUI_EXPORT __declspec(dllexport)
#else
#define SPIKEUI_EXPORT __declspec(dllimport)
#endif
namespace SpikeUI
{
namespace UI
{
struct SPIKEUI_EXPORT Drawable : SpikeUtils::_SpikeEngineObject
{
....
};
}
}
Obviously, all the respective DLL_ defines have been put inside each individual project's C/C++ -> Preprocessor -> Preprocessor definitions, so the projects should build with the appropriate dllimport / dllexport macro.
But when I try and build SpikeUI, I get linker errors like:
LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl
SpikeUtils::_SpikeEngineObject::_SpikeEngineObject(void)" (__imp_??
0_SpikeEngineObject#SpikeUtils##QEAA#XZ) referenced in function "public:
__cdecl SpikeUI::UI::Drawable::Drawable(enum SpikeUI::UI::DrawableType)" (??
0Drawable#UI#SpikeUI##QEAA#W4DrawableType#12##Z)
and
LNK2019 unresolved external symbol "__declspec(dllimport) public: __cdecl
SpikeUtils::_SpikeEngineObject::~_SpikeEngineObject(void)" (__imp_??
1_SpikeEngineObject#SpikeUtils##QEAA#XZ) referenced in function "int
`public: __cdecl SpikeUI::UI::Drawable::Drawable(struct UI::Drawable::dtor$0
const &)'::`1'::dtor$0" (?dtor$0#?0???0Drawable#UI#SpikeUI##QEAA#AEBU012##Z#4HA)
An interesting fact is that Visual Studio even highlights which macro will be used, and for example GUID.h does highlight the dllexport macro, but _SpikeEngineObject.h highlights the dllimport macro for some reason.
Searching through SO and MSDN, it looks like this macro pattern should work, but for some reason it's not consistent on my project.
How can I solve the linker errors?
Answering my own question here:
The SpikeUI project has a dependency on the SpikeUtils project, and it is linked against the .lib and .dll project that is outputed by building the SpikeUtils project.
Now, the problem was that the class _SpikeEngineObject was a header-only class (ie no .cpp for the class). Hence, I am assuming that the SpikeUtils.lib did not contain any symbols for the constructor / destructor etc. of the _SpikeEngineObject, so the linker was having problems linking it.
I solved the problem by adding a .cpp file for the class and implementing dumb constructor / destructor so that the compiler would generate these symbols, and everything was fine.
I must use the ODB framework in my project. I have 2 files: station.hxx and common.hxx with following content:
common.hxx
#ifndef COMMON_HXX
#define COMMON_HXX
#include <string>
#pragma db value
struct ProcessAggregateName
{
#pragma db column("SHORTNAME")
std::string SHORTNAME;
#pragma db column("LONGNAME")
std::string LONGNAME;
#pragma db column("SECONDARYNAME")
std::string SECONDARYNAME;
};
#pragma db value
struct Reporting
{
#pragma db column("OPERATIONALLOG")
std::string OPERATIONALLOG;
#pragma db column("PRINTER")
std::string PRINTER;
#pragma db column("HIGHLIGHTING")
bool HIGHLIGHTING;
#pragma db column("REPORTTYPE")
std::string REPORTTYPE;
};
#endif // COMMON_HXX
station.hxx
#ifndef STATION_HXX
#define STATION_HXX
#include <string>
#include "common.hxx"
#pragma db object table("STATION")
class station
{
public:
station () {}
#pragma db id column("ID")
int ID;
#pragma db column("OPERATINGDOMAIN")
long OPERATINGDOMAIN;
#pragma db column("NAME")
ProcessAggregateName NAME;
#pragma db column("EXPORTBASICDATA")
bool EXPORTBASICDATA;
#pragma db column("EXPORTPROCESSDATA")
bool EXPORTPROCESSDATA;
#pragma db column("IMPORTBASICDATA")
bool IMPORTBASICDATA;
#pragma db column("IMPORTPROCESSDATA")
bool IMPORTPROCESSDATA;
#pragma db column("REPORTING")
Reporting REPORTING;
};
#endif // STATION_HXX
The reason for this: I want to use structures declared in common.hxx also in other files, so I wanted to concentrate them in the same header file and include it whereever I need them. My problem: if I do it this way, I get linker errors like these:
error LNK2019: unresolved external symbol "public: static void __cdecl
odb::access::composite_value_traits::bind(struct odb::mssql::bind *,struct
odb::access::composite_value_traits::image_type &,enum
odb::mssql::statement_kind)"
(?bind#?$composite_value_traits#UProcessAggregateName##$03#access#odb##SAXPAU0mssql#3#AAUimage_type#123#W4statement_kind#43##Z)
referenced in function "public: static void __cdecl
odb::access::object_traits_impl::bind(struct
odb::mssql::bind *,struct odb::access::object_traits_impl::image_type &,enum odb::mssql::statement_kind)"
(?bind#?$object_traits_impl#Vstation##$03#access#odb##SAXPAU0mssql#3#AAUimage_type#123#W4statement_kind#43##Z)
error LNK2019: unresolved external symbol "public: static void __cdecl
odb::access::composite_value_traits::init(struct
odb::access::composite_value_traits::image_type &,struct ProcessAggregateName
const &,enum odb::mssql::statement_kind)"
(?init#?$composite_value_traits#UProcessAggregateName##$03#access#odb##SAXAAUimage_type#123#ABUProcessAggregateName##W4statement_kind#mssql#3##Z)
referenced in function "public: static void __cdecl
odb::access::object_traits_impl::init(struct
odb::access::object_traits_impl::image_type &,class
station const &,enum odb::mssql::statement_kind)"
(?init#?$object_traits_impl#Vstation##$03#access#odb##SAXAAUimage_type#123#ABVstation##W4statement_kind#mssql#3##Z)
If I copy the declaration of ProcessAggregateName and Reporting into station.hxx directly instead of including common.hxx, everything goes fine. What do I do wrong and how can I declare commonly used structures in a single header and include it in multiple *.hxx files?
The odb compiler/code generator creates three elements for the persistence layer - .hxx, .ixx and .cxx files. The .hxx and .ixx files contain the declarations of the types that are needed to perform the persistence. These will satisfy the compiler when building - you tell it what the interface looks like.
However, in order to use the code, you need the implementation files (the definitions). These are only present in the .cxx files.
Without the .cxx files, you get the odb::access… linker errors; these indicate that the code behind the declarations are missing.
Once you make sure that the .cxx files are compiled and linked into your project, the compilation should succeed.
using Visual C++ 2008, I am having an "Unresolved external symbol" even if with the IDE I can correctly see both declaration and definition of the function:
The error:
hook_file.obj : error LNK2001: unresolved external symbol "int __cdecl is_directory_objattr(struct _OBJECT_ATTRIBUTES const *)" (?is_directory_objattr##YAHPBU_OBJECT_ATTRIBUTES###Z)
Relevant code in hook_file.cpp:
#include "misc.h"
void handle_new_file(HANDLE file_handle, const OBJECT_ATTRIBUTES *obj)
{
if(is_directory_objattr(obj) == 0 ) {
// etc.
Declaration in misc.h file:
BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj);
Definition in misc.cpp file:
#include "misc.h"
BOOL is_directory_objattr(const OBJECT_ATTRIBUTES *obj)
{ //function body here }
I really don't get what the linker has to complain here.
The header with function declaration is included by the file which
calls the function.
The cpp file with the function definition included header file with declaration.
Declaration and definitions are identical.
All files are listed among project files.
Any idea whats wrong?
Thanks!
Have you only include one time your header file?
in misc.h
#ifndef MISC
#define MISC
...
#endif MISC ?
I know this is a common problem, but I am pretty sure there is no error with how I include the files.
I'll give you the basic files.
Main.cpp:
#include "GameState.h"
#inlcude "Timer.h"
int main ( int argc, char** argv ) {
GameState.h:
#pragma once
#include "Character.h"
Character.h:
#pragma once
#include "Setup.h"
Setup.h:
#pragma once
#include "SDL.h"
#include "SDL_main.h"
#include "SDL_image.h"
Error report:
Error 1 error LNK2005: "void __cdecl apply_surface(int,int,struct SDL_Surface *,struct SDL_Surface *,struct SDL_Rect *)" (?apply_surface##YAXHHPAUSDL_Surface##0PAUSDL_Rect###Z) already defined in Character.obj C:\Users\Jim\Documents\C++\herorpg\herorpg\Main.obj
Error 2 error LNK2005: "bool __cdecl init(struct SDL_Surface * &)" (?init##YA_NAAPAUSDL_Surface###Z) already defined in Character.obj C:\Users\Jim\Documents\C++\herorpg\herorpg\Main.obj
Error 3 error LNK2005: "bool __cdecl load_files(struct SDL_Surface * * const)" (?load_files##YA_NQAPAUSDL_Surface###Z) already defined in Character.obj C:\Users\Jim\Documents\C++\herorpg\herorpg\Main.obj
Error 4 error LNK2005: "struct SDL_Surface * __cdecl load_image(char *)" (?load_image##YAPAUSDL_Surface##PAD#Z) already defined in Character.obj C:\Users\Jim\Documents\C++\herorpg\herorpg\Main.obj
Error 6 error LNK1169: one or more multiply defined symbols found C:\Users\Jim\Documents\C++\herorpg\Debug\herorpg.exe
Is there anything wrong with what I'm including? If you think more information is required, I'll post the full code. Just seemed like a nuisance before.
C++ has a rule called the one definition rule. Among other things, this rule specifies that there cannot be multiple definitions of a function across your program. You can't have two translation units that both define a function, otherwise you break this rule. You can think of a translation unit as a .cpp file with all of its headers included into the appropriate places.
So if you have a header file, foo.h, that looks like this:
#ifndef FOO_H
#define FOO_H
int foo() { return 5; }
#endif
And then you include this header in two or more .cpp files, each of the translation units will have their own definition. This violates the one definition rule.
To fix this, your header should give a function declaration like so:
#ifndef FOO_H
#define FOO_H
int foo();
#endif
Then, in the corresponding foo.cpp file, give a definition for the function:
#include "foo.h"
int foo() { return 5; }
This means that only the foo.cpp translation unit will have a definition of foo. Any uses of foo in other translation units will be linked to that definition.
An alternative is to declare the function as inline, as in:
#ifndef FOO_H
#define FOO_H
inline int foo() { return 5; }
#endif
The reason this is allowed is because each translation must be able to see the definition of such a function to be able to inline it. However, I don't recommend using inline all willy-nilly.
Linker errors are not caused by #include errors. Linker errors usually happens when the compilers can't find the definition of something. Or if it finds multiple definitions ( such as in this case )
Check if you are linking with multiple SDL libraries or if you have defined the functions yourself somwhere in the code
possible reason:
define functions in header files. functions should only be defined in .cpp file.
looped header files including. like: a.h includes b.h, b.h includes c.h, and c.h includes a.h. Sometime the looped including is not obvious, but it does happen. "#pragma once" can only prevents one header file from being included more than once, but cannot prevent looped including. To solve this problem, using "forward declaration" to replace some #include statements.
some links about forward declaration:
http://en.wikipedia.org/wiki/Forward_declaration
When can I use a forward declaration?
http://msdn.microsoft.com/en-us/library/f432x8c6(v=vs.80).aspx
I was trying to do a DirectX tutorial, but I wanted to write the application in C and not in C++. So I wrote the code in C, but when I tried to compile it I got lot's of errors on the "setupD3D" function. So I just renamed a file to .cpp. But the new code didn't compile either. I think that combining C and C++ is the problem, or there are to many cross-references. Can anyone tell me what the problem is in this code?
direct3d.h:
#include "main.h"
#ifndef DIRECT3D
#define DIRECT3D
int m_videoCardMemory;
char m_videoCardDescription[128];
ID3D11DeviceContext* m_deviceContext = 0;
D3DXMATRIX m_projectionMatrix;
D3DXMATRIX m_worldMatrix;
D3DXMATRIX m_orthoMatrix;
int setupD3D(BYTE vsync, HWND hwnd, float screenDepth, float screenNear);
void terminateD3D();
void beginScene(float red, float green, float blue, float alpha);
void endScene();
#endif
direct3d.cpp
#include "direct3d.h"
// code
main.h:
#ifndef MAIN_FUNC
#define MAIN_FUNC
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")
#include <Windows.h>
#include <dxgi.h>
#include <d3dcommon.h>
#include <d3d11.h>
#include <d3dx10math.h>
#include "direct3d.h"
int breedte, hoogte;
LRESULT CALLBACK Actie(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void main_loop(MSG* msg);
void keyevent();
#endif
main.c
#include "main.h"
// code
winstart.c
#include "main.h"
// code
Errors:
Error 86 error LNK2005: _m_deviceContext already defined in main.obj
Error 87 error LNK2019: unresolved external symbol _setupD3D referenced in function _Actie#16
Error 88 error LNK2019: unresolved external symbol _terminateD3D referenced in function _Actie#16
Error 89 error LNK2019: unresolved external symbol _beginScene referenced in function _render
Error 90 error LNK2019: unresolved external symbol _endScene referenced in function _render
Error 91 error LNK1120: 4 unresolved externals
I also have 84 warnings about macro redefinitions.
If you declare functions in a .cpp file the compiler will compile it as C++ code (no matter if it's pure C or not). Unfortunately C++ has a mechanism called Name mangling which allows for example overloading of functions while C doesn't. If you now want to call such a function fro a .c file (which is recognized as pure C by the compiler) the compiler is creating references for another naming of the symbols (functions in your case) than they exist and the linker is not able to match them anymore.
To solve this, you can put an extern "C" in front of every function you want to be callable by C. As C does not recognize extern "C" you have to make this language dependent.
A common way to solve this problem is to bring follwing structure in the header file:
... your include guard of choice
#ifdef __cplusplus
extern "C" {
#endif
//-- your declarations
#ifdef __cplusplus
}
#endif
This instructs the C++ compiler to create names that are C compliant. As the C compiler does not provide the preprocessor symbol "__cplusplus" it ignores the extern statement. (Which is ok as the C compiler always only creates C compliant symbol names)
Instead of changing header files (sometimes you are not allowed to) it's also legal to include a whole header file embraced by extern "C":
extern "C" {
#include <My_C_API.h>
}
You have two types of link errors :
Error 86 error LNK2005: _m_deviceContext already defined in main.obj
is because you define m_deviceContext in a header file, and then proceed to include that header file in multiple compilation units (at least in direct3d.cpp, main.c and winstart.c). Move definitions out of header files, and also take care of your include dependencies (main.h and direct3d.h depend on each other - that seems odd).
Error 87 error LNK2019: unresolved external symbol _setupD3D referenced in function _Actie#16
Error 88 error LNK2019: unresolved external symbol _terminateD3D referenced in function _Actie#16
Error 89 error LNK2019: unresolved external symbol _beginScene referenced in function _render
Error 90 error LNK2019: unresolved external symbol _endScene referenced in function _render
Error 91 error LNK1120: 4 unresolved externals
is because you're mixing C and C++ code incorrectly. Either compile everything with a C compiler (or a C++ compiler), or make correct use of extern "C". For more details, check eg. the relevant section of the C++ FAQ Lite.
The error says that something is already defined in main.o.
What you do is put the include before the guards, so no matter what it will include that file possibly creating duplicate code. And you have circular dependencies.
In the file direct3d.h:
#include "main.h"
#ifndef DIRECT3D
#define DIRECT3D
it should be:
#ifndef DIRECT3D
#define DIRECT3D
#include "main.h"
The include in main.c:
#include "main.h"
is a problem because you already include it in direct3d.h which is including main.h.
So the compiler probably goes like:
#include "main.h"
#include "direct3d.h"
#include "main.h" <-- duplicate code detected
throw error.
And there is no problem in mixing C and C++ together.