OKay, so I'm trying to set some global variables that can be accessed by the rest of my program by including a header file. However, XCode is telling me that I have duplicate symbols. Can anyone help?
Error: Duplicate symbol _ArrowKey in /Path/to/MKDBControlInterface.o /Path/to/main.o
main.h: // The global variables to be accessed...
#ifndef _main_h
#define _main_h
#include <map>
std::map<int,bool> ArrowKey;
#endif
MKDBControlInterface.h:
#ifndef _MKDBControlInterface_h
#define _MKDBControlInterface_h
#include <map>
#include <GLUT/glut.h>
#include "main.h"
#include "MKDBApplication.h"
class MKDBControlInterface {
public:
MKDBControlInterface( MKDBApplication& App )
: m_App( App )
{
glutSpecialFunc( SpecialListener );
glutSpecialUpFunc( SpecialListenerX );
ArrowKey[GLUT_KEY_LEFT] = false;
ArrowKey[GLUT_KEY_RIGHT] = false;
ArrowKey[GLUT_KEY_UP] = false;
ArrowKey[GLUT_KEY_DOWN] = false;
}
~MKDBControlInterface(){}
void static SpecialListener( int key, int x, int y ){
ArrowKey[key] = true;
}
void static SpecialListenerX( int key, int x, int y ){
ArrowKey[key] = false;
}
private:
MKDBApplication& m_App;
};
#endif
main.cpp
#include "main.h"
#include "MKDBApplication.h"
#include "MKDBControlInterface.h"
#include "MKDBRender.h"
int main( int argc, char *argv[] ){
MKDBApplication App;
MKDBControlInterface Interface( App );
MKDBRender Render( App );
return 0;
}
In main.h you need to declare ArrowKey as
extern "C" std::map<int,bool> ArrowKey;
and in main.cpp after the includes you should define it:
std::map<int,bool> ArrowKey;
BTW, I would also replace #ifndef/#define/#endif with #pragma once in the headers.
Related
I write a lua script and want to parse the script by c++ codes. In this script I have functions, and I want to get the function and save it for usage in the future. The main.cpp is like
#include <string>
#include <iostream>
#include "luaParser.h"
#include "LuaBridge.h"
extern "C" {
# include "lua.h"
# include "lauxlib.h"
# include "lualib.h"
}
using namespace luabridge;
void main (void)
{
lua_State* L = luaL_newstate();
if (luaL_dofile(L, "P3626_PORT.lua"))
{
printf("%s\n", lua_tostring(L, -1));
}
luaL_openlibs(L);
lua_pcall(L, 0, 0, 0);
LuaParser parser;
parser.luaParse(L); // get some values from the luaParser::luaParse function
lua_close(L);
parser.run(); // call the run function defined in LuaParser class
parser.stop(); // call the stop function defined in LuaParser class
}
The P3626_PORT.lua is like:
lua_name = "P3626_PORT.lua"
run = function()
print (" this is my input!!!!!!!")
end
stop = function()
print (" this is my output!!!!!!!")
end
The luaParser.h is like:
#pragma once
#include <string>
#include "LuaBridge.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
using namespace luabridge;
class LuaParser
{
public:
LuaParser();
virtual ~LuaParser();
void luaParse(lua_State* L); // in this function, run (pcall) the script and retrieve functions
void run();
void stop();
private:
LuaRef mRun;
LuaRef mStop;
};
And at last, luaParser.cpp is like this:
#ifdef _WIN32
#pragma warning(disable: 4786)
#endif
#include <stdlib.h>
#include <assert.h>
#include "LuaParser.h"
#include <iostream>
#include <string>
LuaParser::LuaParser(){}
LuaParser::~LuaParser(){}
void LuaParser::luaParse(lua_State* L)
{
using namespace luabridge;
LuaRef serviceName = getGlobal(L, "service_name");
std::string LuaServiceName = serviceName.cast<std::string>();
std::cout << LuaServiceName << std::endl;
// now Let's read the function
mRun = getGlobal(L, "run");
mStop = getGlobal(L, "stop");
}
void LuaParser::run()
{
mRun();
}
void LuaParser::stop()
{
mStop();
}
When compiling the project, I get the error
error c2512: 'luabridge::LuaRef':no appropriate default constructor available
I have tried to solve this problem by such as initializing list but it doesn't work. Any idea how to solve this problem?
This question already has answers here:
Why does global variables in a header file cause link error?
(5 answers)
Closed 7 years ago.
I know, there are a lot of similar problems and solutions already on SO, and I read them, but none of them helped me solve my problem.
I created a class for logging.
Here is Logger.h
#ifndef LOGGER_H
#define LOGGER_H
namespace Logger
{
namespace debug
{
int Error = 0, OtherNumber;
class log
{
public: // Methods
void Save();
private: // Members
static int indentation;
const std::wstring context;
int Type, LineNumber;
public: // Constructor, Destructor
log( const std::wstring& context, int LineNumber, int Type );
~log();
};//class log
}//namespace debug
}//namespace Logger
#endif //LOGGER_H
Logger.cpp
#include "stdafx.h"
#include "Logger.h"
namespace Logger
{
namespace debug
{
log::log( const std::wstring& ctx, int linenr, int type ): context( ctx ), LineNumber( linenr ), Type( type )
{
printf("\nLogging start! Context = %ls - Line = %d - Type = %d", context.c_str(), LineNumber, Type );
}
log::~log()
{
printf( "\nLogging end! Context = %ls - Line = %d - Type = %d", context.c_str(), LineNumber, Type );
printf( "\nUsing Error here =%d", Error );
}
void log::Save()
{
FILE *fp = NULL;
fclose( fp );
fp = fopen( "mylogfile.log", "a" );
}
}//namespace debug
}//namespace Logger
Then in main.h I have:
#ifndef MYAPP_H
#define MYAPP_H
#include "Logger.h"
#define WIDEN2( x ) L ## x
#define WIDEN( x ) WIDEN2( x )
#define WFILE WIDEN( __FILE__ )
#define __STR2WSTR( str ) L##str
#define _STR2WSTR(str) __STR2WSTR(str)
#define WFUNCTION _STR2WSTR( __FUNCTION__ )
#define DEBUGLOG_START( Type ) Logger::debug::log _debugLog( WFUNCTION, __LINE__, Type );
#define DEBUGLOG_SAVE { _debugLog.Save(); }
#endif //MYAPP_H
And finally in main.cpp I have:
#include "Test_UserPart.h"
int _tmain(int argc, _TCHAR* argv[])
{
DEBUGLOG_START( 1 )
Logger::debug::OtherNumber = 10;
_getch();
return 0;
}
When I want to compile it I get the error error LNK2005: "int Logger::debug::Error" (?Error#debug#Logger##3HA) already defined in Logger.obj ...MyApp.obj
So as far as I see, I didn't make any circular includes. But why do I get this error?
Thanks!
You're defining variables in the header, leading to multiple definitions when that header is included from more than one source file. Instead, declare them in the header:
extern int Error = 0, OtherNumber;
^^^^^^
and define them in just one source file. Or stop using global variables.
MainGame.h
#ifndef MainGame_h
#define MainGame_h
#include <string>
#include <sstream>
#include "Horde3D.h"
//definitions
#endif MainGame_h
MainGame.cpp
#include <math.h>
#include <iomanip>
#include "Horde3DUtils.h"
#include "MainGame.h"
#include "GameConfig.h" //<--
//code
main.cpp
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include "glfw.h"
#include "MainGame.h"
#include "GameConfig.h" //<--
//code
GameConfig.h
#ifndef GameConfig_h
#define GameConfig_h
#include <string>
#include <sstream>
#define MAX_PATH 260
class GameConfig
{
static std::string ExtractStartupPath(char *full_app_path)
{
const std::string s(full_app_path);
if(s.find( "/" ) != std::string::npos)
return s.substr( 0, s.rfind( "/" )) + "/";
else if(s.find( "\\" ) != std::string::npos )
return s.substr( 0, s.rfind( "\\" )) + "\\";
else
return "";
}
public:
static bool IsFullScreen;
static int StatMode;
static int FreezeMode;
static bool DebugViewMode;
static bool WireframeMode;
static char *GameTitle;
static int WindowWidth, WindowHeight;
static char StartupPath[MAX_PATH];
static char ContentPath[MAX_PATH];
static void Initialize(char *startup_path)
{
GameTitle = "TestGame\0";
std::string startup_dir = ExtractStartupPath(startup_path);
memcpy(StartupPath, startup_dir.c_str(), startup_dir.length() * sizeof(char));
std::string path(StartupPath);
path.erase(path.find_last_of('\\'), std::string::npos);
path.append("\\Content");
memcpy(ContentPath, path.c_str(), path.length() * sizeof(char));
}
};
int GameConfig::StatMode = 0;
int GameConfig::FreezeMode = 0;
bool GameConfig::DebugViewMode = false;
bool GameConfig::WireframeMode = false;
bool GameConfig::IsFullScreen = false;
int GameConfig::WindowWidth = 800;
int GameConfig::WindowHeight = 600;
char GameConfig::StartupPath[MAX_PATH] = { 0 };
char GameConfig::ContentPath[MAX_PATH] = { 0 };
char *GameConfig::GameTitle = "TestGame\0";
#endif GameConfig_h
When compiling it I getting linker errors...
main.obj : error LNK2005: "public: static int GameConfig::StatMode" (?StatMode#GameConfig##2HA) is already define in в MainGame.obj
But I don't understand why... There are only two includes of GameConfig - one in MainGame.cpp and second in main.cpp. Those should never cross. And even if they crossed, what #ifndef GameConfig_h, #define GameConfig_h and #endif GameConfig then for?
I use VC++ 2010 Express Edition
Include guards help you avoid including the same file more than once from the same translation unit. However, since the translation units are processed independently, both of them will get the included code, and therefore produce duplicate definitions.
To avoid this problem you need to move definitions out of the header and into a CPP file:
GameConfig.cpp:
#include "GameConfig.h"
int GameConfig::StatMode = 0;
int GameConfig::FreezeMode = 0;
bool GameConfig::DebugViewMode = false;
bool GameConfig::WireframeMode = false;
bool GameConfig::IsFullScreen = false;
int GameConfig::WindowWidth = 800;
int GameConfig::WindowHeight = 600;
char GameConfig::StartupPath[MAX_PATH] = { 0 };
char GameConfig::ContentPath[MAX_PATH] = { 0 };
char *GameConfig::GameTitle = "TestGame\0";
You need to move initialisation of the statics to GameConfig.cpp.
Each source file which includes GameConfig.h is picking up a their own copy of these variables at present.
The instanciations of your static members shouldn't be in the .h file but in the corresponding .cc file.
Otherwise they are instantiated in every compilation unit.
Include guards are only useful inside a single compilation unit (ie one single cpp file). Since the cpp files are compiled separately, for each file the include guard will start as undefined and therefore the .h file will be included twice, once for each cpp file. If the .h file includes for example a function definition, it will be defined twice.
Normally you make the problem "go away" by putting only declarations in the h files, and actually defining the functions in cpp files. That way, the function will only be defined once.
I am compiling a program agains LLVM-CLANG. This is the main
#include <iostream>
#include "CompilerFactory.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
int main(int argc, char const *argv[])
{
using clang::CompilerInstance;
using clang::TargetOptions;
using clang::TargetInfo;
using clang::FileEntry;
using clang::Token;
using clang::DiagnosticOptions;
using clang::TextDiagnosticPrinter;
CompilerInstance ci;
CSFV::CompilerFactory::GetCompilerInstance(ci);
const FileEntry *pFile = ci.getFileManager().getFile("test.c");
ci.getSourceManager().createMainFileID(pFile);
ci.getPreprocessor().EnterMainSourceFile();
ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(),
&ci.getPreprocessor());
Token tok;
do
{
ci.getPreprocessor().Lex(tok);
if (ci.getDiagnostics().hasErrorOccurred())
break;
ci.getPreprocessor().DumpToken(tok);
std::cerr << std::endl;
} while (tok.isNot(clang::tok::eof));
ci.getDiagnosticClient().EndSourceFile();
return 0;
}
and this is the included class
//If they are not defined we have an error at compile time
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include "llvm/Support/Host.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
namespace CSFV{
class CompilerFactory
{
public:
CompilerFactory();
~CompilerFactory();
/// \brief Generate and returns a compiler instance object
static void GetCompilerInstance(CompilerInstance &ci){
DiagnosticOptions diagOpts;
TextDiagnosticPrinter* diagPrinter =
new TextDiagnosticPrinter(llvm::outs(), &diagOpts, true);
ci.createDiagnostics(diagPrinter);
llvm::IntrusiveRefCntPtr<TargetOptions> pto (new TargetOptions());
pto->Triple = llvm::sys::getDefaultTargetTriple();
TargetInfo *pti =
TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto.getPtr());
ci.setTarget(pti);
ci.createFileManager();
ci.createSourceManager(ci.getFileManager());
ci.createPreprocessor();
return;
}
};
} //end of namespace CSFV
For some reason I get a segfault at the end of the execution of the main. What am I missing?
I don't know if this is the same problem I had, but what I did was declare the targetoptions as a new pointer.
eg:
clang::TargetOptions *targetOpts=new clang::TargetOptions;
I have a feeling targetinfo cleans it up when itself is destroyed.
I have a problem with the code OpenKinect provides. I'm trying to use the Kinect with c++, but I get this error. On the web this question was already asked, but I have not find a decent answer. The code is this:
#include <cstdlib>
#include "libfreenect.h"
#include "libfreenect.hpp"
#include <pthread.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#if defined(__APPLE__)
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#endif
using namespace std;
class Mutex {
...
};
class MyFreenectDevice : public Freenect::FreenectDevice {
public:
MyFreenectDevice(freenect_context *_ctx, int _index)
: Freenect::FreenectDevice(_ctx, _index),
m_buffer_depth(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes),
m_buffer_video(freenect_find_video_mode(FREENECT_RESOLUTION_MEDIUM, FREENECT_VIDEO_RGB).bytes),
m_gamma(2048),
m_new_rgb_frame(false),
m_new_depth_frame(false)
{
for (unsigned int i = 0; i < 2048; i++) {
float v = i / 2048.0;
v = std::pow(v, 3) * 6;
m_gamma[i] = v * 6 * 256;
}
}
...
private:
std::vector<uint8_t> m_buffer_depth;
std::vector<uint8_t> m_buffer_video;
std::vector<uint16_t> m_gamma;
Mutex m_rgb_mutex;
Mutex m_depth_mutex;
bool m_new_rgb_frame;
bool m_new_depth_frame;
};
Freenect::Freenect freenect;
MyFreenectDevice* device;
freenect_video_format requested_format(FREENECT_VIDEO_RGB);
...
I get the error Unable to resolve identifier identifier freenect for the instruction Freenect::Freenect freenect;.
The code of this template is in the libfreenect.hpp code:
class Freenect : Noncopyable {
private:
typedef std::map<int, FreenectDevice*> DeviceMap;
public:
...
template <typename ConcreteDevice>
ConcreteDevice& createDevice(int _index) {
DeviceMap::iterator it = m_devices.find(_index);
if (it != m_devices.end()) delete it->second;
ConcreteDevice * device = new ConcreteDevice(m_ctx, _index);
m_devices.insert(std::make_pair<int, FreenectDevice*>(_index, device));
return *device;
}
...
}
I have no idea of what is the problem, this is the official code and it should work.. any suggestions? thanks in advance