문제

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

도움이 되었습니까?

해결책

The linker is complaining about two of your functions being defined multiple times. As you could probably figure out from the errors, these functions are:

irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)
irr::scene::RTSCamera::OnRegisterSceneNode(void)

What's most likely happening here is that these two functions are defined in a header file, but:

  • Their definition does not appear directly in the class definition (so they are not implicitly declared to be inline);
  • Their out-of-class definition in the header file is not explicitly marked as inline.

As a result, if the header is included multiple times in different translation units (i.e. in different .cpp files), multiple definitions of the same functions will end up being present in the object code of those translation units.

When merging them, the linker will complain that you are breaking the ODR (One Definition Rule).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top