I defined namespace "MAPDATA" in a header file(MapData.h) that I have created,and I defined a variable in
"MAPDATA".
MapData.h
namespace MAPDATA{
cocos2d::CCSize MapSizeData;
cocos2d::CCSize TileSizeData;
int MaxTileXData;
int MaxTileYData;
}
However, If I write #include "MapData.h" in else class,Linker appear the following error.
duplicate symbol __ZN7MAPDATA11MapSizeDataE in:
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/TileMapManage.o
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/MapData.o
duplicate symbol __ZN7MAPDATA12TileSizeDataE in:
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/TileMapManage.o
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/MapData.o
duplicate symbol __ZN7MAPDATA12MaxTileXDataE in:
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/TileMapManage.o
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/MapData.o
duplicate symbol __ZN7MAPDATA12MaxTileYDataE in:
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/TileMapManage.o
/Users/nyoronyoro-kun/Desktop/出力先/Build/Intermediates/tilegame.build/Debug-iphonesimulator/tilegame.build/Objects-normal/i386/MapData.o
ld: 4 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
But, If I remove name(MAPDATA) of namespace and write #include "MapData.h" in else class, the error disappeared.
After remove name of namespace
namespace {
cocos2d::CCSize MapSizeData;
cocos2d::CCSize TileSizeData;
int MaxTileXData;
int MaxTileYData;
}
If someone could explain clearly why the error disappeared,I would be forever grateful.
This is a fairly common error due to the fact that any implementation file that includes that header will contain a definition of those variables. This will lead to duplicate symbols during linking.
It is resolved by defining a single instance of each of those objects in a new, separate, .cpp file. Also it's not clear to me why you are using a namespace with no name.
So first declare those objects with extern:
MapData.h:
extern cocos2d::CCSize MapSizeData;
extern cocos2d::CCSize TileSizeData;
extern int MaxTileXData;
extern int MaxTileYData;
And then add a source file containing the definition of those object:
MapData.cpp:
#include "MapData.h"
#include .... // other files
cocos2d::CCSize MapSizeData;
cocos2d::CCSize TileSizeData;
int MaxTileXData;
int MaxTileYData;
Note also, that you might want to put those variables into a class, which can be initialised properly and can maintain all the positive aspects of object orientation.
Related
I have two files, main.ccp and namespace.cpp (Not the actual names, but for simplification)
My namespace.cpp can be boiled down to the following:
#pragma once
namespace MyNamespace {
int A = 0;
}
And my main.cpp basically just uses the content of MyNamespace:
#include "namespace.cpp"
int main() {
...
// Using MyNamespace::A
...
}
But I keep getting a LNK2005 error in MyNamespace.obj, that A is already defined in main.obj.
Which is weird: It's not like I've defined it twice. I'm literally just using it in my main file, but since I wanted to clean up my main file a little bit I put it into it's own file and into a namespace.
I don't understand where the problem is, would appreciate help.
Thanks
I have read this informative stackoverflow question regarding unresolved external symbols, but I am still not sure how to solve my issue.
Within Visual Studio 2012, I have a solution consisting of multiple projects, one of which is a static library called common. Each project that produces an executable consists of a header and associated cpp file of all global functions used throughout that specific program, called programglobals. In the process of developing one of these projects, I started duplicating some of this code from one project's programglobals to another. Now that I have completed all the projects, I want to extract the duplicate code into a associated header and cpp file within the common library, but I believe I might be referencing them incorrectly, which is producing these unresolved external symbol errors
Here is a dumbed down example of what I am currently attempting.
Common Library Files
//solutionglobals.h
void commonFunction();
//solutionglobals.cpp
void commonFunction() {
int asdf;
}
Project A Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectA();
// programglobals.cpp
void functionUsedInProjectA() {
int x;
}
// output.h
#include "programglobals.h"
void asdfA();
// output.cpp
void asdfA() {
int x;
functionUsedInProjectA();
commonFunction();
}
Project B Files
// programglobals.h
#include "../common/solutionglobals.h
void functionUsedInProjectB();
// programglobals.cpp
void functionUsedInProjectB() {
int x;
}
// output.h
#include "programglobals.h"
void asdfB();
// output.cpp
void asdfB() {
int x;
functionUsedInProjectB();
commonFunction();
}
Any reference to commonFunction() results in an unresolved external symbol error.
Thanks!
You will have to specify in your executable projects that they reference the static lib. May be http://msdn.microsoft.com/en-us/library/vstudio/ms235627%28v=vs.110%29.aspx#uselibinapp helps (lower third of the article).
Before you can use the math routines in the static library, you must
reference it. To do this, open the shortcut menu for the MyExecRefsLib
project in Solution Explorer, and then choose References. In the
MyExecRefsLib Property Pages dialog box, expand the Common Properties
node, select Framework and References, and then choose the Add New
Reference button.
The linker cannot 'see' your function and as such thinks that it does not have an external symbol referencing it, hence the error.
You must #pragma comment(lib, [library here]) to reference the external function.
The following code can be used to reproduce this error:
[header file- test.h]:
#include "StdAfx.h"
void someOtherFunction();
void someFunction(string thisVar);
[code file- test.cpp]:
#include "StdAfx.h"
#include "test.h"
void someOtherFunction()
{
printf("Hello World!");
}
[function body for someFunction(string thisVar) is missing!]
when I compile the following c++ code:
#include "ConstantList.h"
using namespace std;
int main() {
ConstantList* cl = new ConstantList();
//do something with cl
delete cl;
cl = NULL;
return 0;
}
The compiler gives me the error:
Undefined symbols:
"ConstantList::~ConstantList()", referenced from:
_main in ccNfeeDU.o
"ConstantList::ConstantList()", referenced from:
_main in ccNfeeDU.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Am I not getting the syntax right for instantiating an object?
My ConstantList.h file looks like this:
#ifndef ConstantList_h
#define ConstantList_h
#include <string>
#include "Token.h"
using namespace std;
class ConstantListTail;
class ConstantList {
public:
ConstantList();
~ConstantList();
std::string toString();
void push_back(Token*);
void push_back(ConstantListTail*);
private:
Token* termString;
ConstantListTail* constantListTail;
};
#endif
Any help is greatly appreciated!
Your syntax is correct, because you are getting a linker error, not a compiler error. This error means that you are compiling your main without the source of the ConstantList.cpp, or linking without a reference to ConstantList.o
Compiling with this command should fix the error:
g++ collect2.cpp ConstantList.cpp
(I am assuming that the file with your main function is called collect2.cpp).
"undefined symbol" means you have declared the identifier (in this case the destructor), and it's used, but as far as the linker knows you have not defined it
add a definition somewhere, and make sure the compiled version is in one of the files the linker links
re "syntax for instantiation", unfortunately there is no dedicated syntax for that in C++
instead the functional cast notation is used for constructor invocations
perhaps the closest you get to a pure instantiation syntax is the new expression
re
using namespace std;
in a header file: don't.
for example, the standard library defines something called distance. what are the chances that some code that includes the header will have its own distance, and get a name collision? much higher than zero.
this doesn't mean you should never have using namespace std; in a header file, but you should never have it in the global namespace in a header file. and for other namespaces, be very aware of what that does, namely offering all the standard library names as part of also that namespace.
I have 2 static libraries from «vendor1» and «vendor2»:
vendor1.lib and vendor1.h;
vendor2.lib and vendor2.h.
In the file, vendor1.h. The following declaration is there:
double Min();
In the file, vendor2.h. The following declaration is there:
double Min();
In my client file:
include "vendor1.h"
include "vendor2.h"
double x = Min();
It by defaults calls vendor1.h. I tried introducing the namespace:
namespace vendor1 {
include "vendor1.h"
}
namespace vendor2 {
include "vendor2.h"
}
A call to the following function
double xx = vendor2::Min();
I get the following linker errors:
Client.cpp 1>Client.obj : error LNK2019: unresolved external symbol "double __cdecl vendor2::Min(void)" (?Min#vendor2##YANXZ) referenced
in function _wmain 1>c:\temp\Client\Debug\Client.exe : fatal error
LNK1120: 1 unresolved externals
How can I fix this without creating wrappers for each of the wrappers?
If you have two static libraries with conflicting names you won't be able to link your program statically! The static linker will just go and find the first symbol matching an undefined symbol and choose this. Wrapping the names into a namespace doesn't help: this changes the namespace being expected in the library. You just found why namespace are a good thing.
How to solve the problem? I'm not aware of an approach which is based on the C++ standard. Practically, you may be able to do something: create a dynamic library which forwards to your conflicting functions but puts the name into separate namespaces (or uses different names). The dynamic libraries are linked with individual static libraries, i.e. the conflict doesn't happen at this time. You will probably also need to avoid the underlying names being visible from the symbols in the shared library. The details on how this is done depend on the compiler and I don't know who to deal with MSVC++ for things like this.
How about wrapping the functions into different namespaces?
vendor1_wrapper.h:
namespace vendor1 {
double Min();
}
vendor1_wrapper.cpp:
#include "vendor1_wrapper.h"
#include "vendor1.h"
namespace vendor1 {
double Min()
{
return Min();
}
}
vendor2_wrapper.h:
namespace vendor2 {
double Min();
}
vendor2_wrapper.cpp:
#include "vendor2_wrapper.h"
#include "vendor2.h"
namespace vendor2 {
double Min()
{
return Min();
}
}
Now you can use the functions using namespaces (your client file):
#include "vendor1_wrapper.h"
#include "vendor2_wrapper.h"
...
vendor1::Min();
vendor2::Min();
i have a full static class, using a std::map
thats the simplified case
.h
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <map>
class Keyboad {
static std::map<char, bool> pressed;
static void keyPressedEvent(char _key);
};
#endif
.cpp
#include "Keyboard.h"
void Keyboard :: keyPressedEvent(char _key) {
Keyboard :: pressed[_key] = true;
}
but there is a problem with the static member variable, because i get
Undefined symbols:
"Keyboard::pressed", referenced from:
__ZN15Keyboard7pressedE$non_lazy_ptr in Keyboard.o
(maybe you meant: __ZN15Keyboard7pressedE$non_lazy_ptr)
ld: symbol(s) not found
collect2: ld returned 1 exit status
when i remove it, it runs ok
why do i get this problem, there should be no problem when using a static variable :/
thanks
You need to define the pressed map in your .cpp file:
#include "Keyboard.h"
std::map<char, bool> Keyboard::pressed;
// The rest as before
You should add this to .cpp file
std::map<char, bool> Keyboad::pressed;
Consider static class members as global variables. Compiler should allocate memory for them inside of the only object file. So you should define them in corresponding source file.
A static member in the class definition is just a declaration. You
still have to provide the definition, exactly like you did for the
function. Just add
std::map<char, bool> Keyboard::pressed;
in a source file somewhere. (For mapping chars, you might also
consider a simple
bool Keyboard::pressed[256];
, indexed with the char converted to unsigned char.)
Consider a simpler case. A global variable counter is declared in multiple header files:
int counter; // This appears in 3 HEADER files.
Few source files do refer it. When you compile and link it, compiler would emit linker error saying that counter is already defined in some set of .OBJ files (Error message is dependent on compiler).
To solve this, you just put extern in front of variable (in all header files):
extern int counter; // This appears in 3 HEADER files.
And when you rebuild it, linker will complain that counter is not defined anywhere.
To solve this issue, you define this variable in one source file (any one):
int counter;
And it resolves the issue.
The static-variable of class is nothing but a global variable, which can be accessed by classname::variablename format. The accessibility is same - global.