I'm having an issue with a pretty simple code I am following the tutorial of chrono::engine http://www.chronoengine.info/mediawiki/index.php/Demo_fourbar I do not have much experience in C++ programming (I have some experience in Java), therefore I tried to define MyEventReceiver (a class from the tutorial) in a different file (MyEventReceiver.h and MyEventReceiver.cpp) to get my head around classic structure of a C++ code
Here is the version of the code
MyEventReceiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"
#include "core/CHrealtimeStep.h"
#include <irrlicht.h>
// Use the namespace of Chrono
using namespace chrono;
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(ChSystem* asystem, IrrlichtDevice* adevice, ChSharedPtr<ChLinkEngine> aengine);
bool OnEvent(const SEvent& event);
void setText_enginespeed(IGUIStaticText* _text_enginespeed);
IGUIStaticText* getText_enginespeed();
private:
IGUIStaticText* text_enginespeed;
ChSystem* msystem;
IrrlichtDevice* mdevice;
ChSharedPtr<ChLinkEngine> mengine;
};
#endif
with the implementation as follows in MyEventReceiver.cpp
#include "MyEventReceiver.h"
// Constructor
MyEventReceiver::MyEventReceiver(ChSystem *asystem, IrrlichtDevice *adevice, ChSharedPtr<ChLinkEngine> aengine)
{
// store pointer to physical system & other stuff
// so we can tweak them by user keyboard
msystem = asystem;
mdevice = adevice;
mengine = aengine;
}
bool MyEventReceiver::OnEvent(const SEvent& event)
{
// check if user moved the sliders with mouse..
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = mdevice->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_SCROLL_BAR_CHANGED:
if (id == 101) // id of 'engine speed' gui
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
double newspeed = 10*(double)pos/100.0;
// set the speed into engine object
ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
spe_funct->Set_yconst(newspeed);
// show speed as formatted text in interface screen
char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
text_enginespeed->setText(core::stringw(message).c_str());
}
break;
}
}
return false;
}
void MyEventReceiver::setText_enginespeed(IGUIStaticText* _text_enginespeed)
{
text_enginespeed = _text_enginespeed;
}
IGUIStaticText* MyEventReceiver::getText_enginespeed()
{
return text_enginespeed;
}
and the main file in Main_2.cpp (which I emptied, it gives me the same error with or without the code inside - which is basically only setting up the 3D engine Irrlicht and some mechanics features from the collision model of chrono::engine)
#include "MyEventReceiver.h"
int main()
{
return 0;
}
Basically the code defines an event receiver, so that the user after running the program can interact with the 3D environment built from the chrono::engine and Irrlicht engine through GUI manipulation I define all the required libraries in the MyEventReceiver.h file and the required namespaces
The problem is that it does not compile (please note that I already tested the engines - with the same #include and using namespaces in just one file and it was working in a different project - ), i think the problem is coming from the structure of the header files
I got those lines of error
1>MyEventReceiver.obj : error LNK2005: "public: virtual bool __thiscall irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)" (?OnEvent@RTSCamera@scene@irr@@UAE_NABUSEvent@3@@Z) already defined in Main_2.obj
1>MyEventReceiver.obj : error LNK2005: "public: virtual void __thiscall irr::scene::RTSCamera::OnRegisterSceneNode(void)" (?OnRegisterSceneNode@RTSCamera@scene@irr@@UAEXXZ) already defined in Main_2.obj
etc... (it goes on like this) and the final mistake
1>C:\Users\****\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\TutorialChronoEngine_2.exe : fatal error LNK1169: one or more multiply defined symbols found
I am using Visual Studio 2010 C++. I defined one global solution, and several projects in this very solution (the program I wrote above is one project among others) I am sure it must be pretty easy to solve, but can't really find the solution. Let me know if you need further details
Thanks a lot Best regards Vincent
Edit : If I put all the codes in one single file as follows
#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"
#include <irrlicht.h>
// Use the namespace of Chrono
using namespace chrono;
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Get rid of the command windows that pops up when compiling and running
#ifdef _IRR_WINDOWS_
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
IGUIStaticText* text_enginespeed = 0;
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(ChSystem* asystem,
IrrlichtDevice *adevice,
ChSharedPtr<ChLinkEngine> aengine)
{
// store pointer to physical system & other stuff
// so we can tweak them by user keyboard
msystem = asystem;
mdevice = adevice;
mengine = aengine;
}
bool OnEvent(const SEvent& event)
{
// check if user moved the sliders with mouse..
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = mdevice->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_SCROLL_BAR_CHANGED:
if (id == 101) // id of 'engine speed' gui
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
double newspeed = 10*(double)pos/100.0;
// set the speed into engine object
ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
spe_funct->Set_yconst(newspeed);
// show speed as formatted text in interface screen
char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
text_enginespeed->setText(core::stringw(message).c_str());
}
break;
}
}
return false;
}
private:
ChSystem* msystem;
IrrlichtDevice* mdevice;
ChSharedPtr<ChLinkEngine> mengine;
};
int main(int argc, char* argv[])
{
return 0;
}
In that way, I avoid defining several times functions from the Irrlicht 3D engine that are not defined as inline. Unfortunately, this way of coding can become really cumbersome if a project becomes big (having to define all classes that rely on the 3D engine in one unique .cpp file), is there a design pattern to follow so that it is possible to avoid multiple defined objects with each class defined in a separate file ?
Thanks a lot
Best
Vincent