LNK 2005 errors. Topic is solved

Do you have a question about makefiles, a compiler or IDE you are using and need to know how to set it up for wxWidgets or why it doesn't compile but other IDE's do ? Post your questions here.
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

LNK 2005 errors.

Post by bugmenot »

I keep getting these errors:
TopFrame.obj : error LNK2005: "protected: virtual struct wxEventTable const * __thiscall LCtrl::GetEventTable(void)const " (?GetEventTable@LCtrl@@MBEPBUwxEventTable@@XZ) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "protected: virtual class wxEventHashTable & __thiscall LCtrl::GetEventHashTable(void)const " (?GetEventHashTable@LCtrl@@MBEAAVwxEventHashTable@@XZ) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "public: void __thiscall LCtrl::Insert(class wxListEvent &)" (?Insert@LCtrl@@QAEXAAVwxListEvent@@@Z) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "public: void __thiscall LCtrl::Delete(class wxListEvent &)" (?Delete@LCtrl@@QAEXAAVwxListEvent@@@Z) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "protected: static struct wxEventTable const LCtrl::sm_eventTable" (?sm_eventTable@LCtrl@@1UwxEventTable@@B) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "private: static struct wxEventTableEntry const * const LCtrl::sm_eventTableEntries" (?sm_eventTableEntries@LCtrl@@0QBUwxEventTableEntry@@B) already defined in ListCTRL.obj
TopFrame.obj : error LNK2005: "protected: static class wxEventHashTable LCtrl::sm_eventHashTable" (?sm_eventHashTable@LCtrl@@1VwxEventHashTable@@A) already defined in ListCTRL.obj
Debug/wxMP.exe : fatal error LNK1169: one or more multiply defined symbols found
No other errors, I believe the problem results from me sucking at multiple files(before this, I've always mashed everything into the same file because multiple files resulted in frustration). I've tried the same code in a single file and it works fine. The top frame and a list control both have an event table in their own files, sepperate from real code. I get the feeling that it's something easy causing it, so I'm not going to post any code unless it's not as common as I think..

Code: Select all

BEGIN_EVENT_TABLE(LCtrl, wxListCtrl)
	EVT_LIST_INSERT_ITEM(LIST_CTRL, LCtrl::Insert)
	EVT_LIST_DELETE_ITEM(LIST_CTRL, LCtrl::Delete)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(TopFr, wxFrame)
    EVT_MENU(ID_Quit, TopFr::OnQuit)
    EVT_MENU(ID_About, TopFr::OnAbout)
	EVT_MENU(ID_Pick, TopFr::OnPick)
	EVT_MENU(ID_Save, TopFr::OnSave)
	EVT_MENU(ID_SaveAs, TopFr::OnSaveAs)
	EVT_MENU(ID_Load, TopFr::OnLoad)
END_EVENT_TABLE()
Thanks in advance for the patience :P

This is in VS.NET 2003**
Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

Here is a shot in the dark

How are you defining the header files for your seperate files.

e.g.

Code: Select all

//Nothing but comments before these defines
#define MY_HEADER_FILE_H
#ifndef MY_HEADER_FILE_H

//include files go here
#include <wx/SomeWxFile.h>
#include "MyOtherFile.h"

//Class and function declarations next
class MyClass
{
     public:
         MyClass();
         ~MyClass();
};

void ARandomFunction()
{
      //Do something random here
};

#endif

The reason I ask is it looks like there are multiple declartions in your code. One reason for this is #include statements being mada before a #define section. This means the same code in the #include files gets included multiple times and the compiler gets confused.

Sof.T
leio
Can't get richer than this
Can't get richer than this
Posts: 802
Joined: Mon Dec 27, 2004 10:46 am
Location: Estonia, Tallinn

Post by leio »

Sof_T wrote:

Code: Select all

//Nothing but comments before these defines
#define MY_HEADER_FILE_H
#ifndef MY_HEADER_FILE_H
That should be the other way around.
Compilers: gcc-3.3.6, gcc-3.4.5, gcc-4.0.2, gcc-4.1.0 and MSVC6
OS's: Gentoo Linux, WinXP; WX: CVS HEAD

Project Manager of wxMUD - http://wxmud.sf.net/
Developer of wxGTK;
gtk+ port maintainer of OMGUI - http://www.omgui.org/
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

Post by bugmenot »

Topframe.cpp:

Code: Select all

#include "wx/wx.h"
#include "wx/listctrl.h"
#include "TopFrame.h"
#include "ListCTRL.cpp"

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit()
{
	TopFr *frame = new TopFr("rawr", 
         wxPoint(430,430), wxSize(640,480));
    frame->Show(TRUE);
    SetTopWindow(frame);
    return TRUE;
}

 
TopFr::TopFr(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
{
    wxMenu *menuFile = new wxMenu;
    menuFile->Append(ID_Save, "&Save");
	menuFile->Append(ID_SaveAs, "Save &As...");
	menuFile->Append(ID_Load, "&Load");
    menuFile->AppendSeparator();
    menuFile->Append(ID_Quit, "E&xit");

	wxMenu *menuGo = new wxMenu;
	menuGo->Append(ID_Pick, "&Pick");

	wxMenu *menuHelp = new wxMenu;
	menuHelp->Append(ID_About, "&About");
 
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append(menuFile, "&File");
	menuBar->Append(menuGo, "&Go");
	menuBar->Append(menuHelp, "&Help");
 
    SetMenuBar(menuBar);

    CreateStatusBar();
    SetStatusText("rawr");

	wxPanel *MainP = new wxPanel(this, -1, wxDefaultPosition,
		wxDefaultSize);

	//LCtrl *Lctrl;

	/*Lctrl = dynamic_cast<LCtrl*>(new wxListCtrl(MainP, LIST_CTRL,
		wxPoint(20, 140), wxSize(600, 340)
		, wxLC_REPORT | wxLC_HRULES));*/

	LCtrl *Lctrl = new LCtrl(MainP, LIST_CTRL, 
		wxPoint(20, 140), wxSize(600, 340)
		, wxLC_REPORT | wxLC_HRULES);

	wxListItem itemCol;
    itemCol.SetText(_T("Column 1"));
    Lctrl->InsertColumn(0, itemCol);

	Lctrl->Show();
}

 
void TopFr::OnQuit(wxCommandEvent& WXUNUSED(event))
{
    Close(TRUE);
}
 
void TopFr::OnAbout(wxCommandEvent& WXUNUSED(event))
{
	wxMessageBox("rawr",
        "rawr", wxOK | wxICON_INFORMATION, this);
}

void TopFr::OnPick(wxCommandEvent& WXUNUSED(event))
{
	wxMessageBox("rawr", "rawr",
		wxOK | wxICON_INFORMATION,
		this);
}

void TopFr::OnSave(wxCommandEvent& WXUNUSED(event))
{
	wxMessageBox("rawr", "rawr",
		wxOK | wxICON_INFORMATION,
		this);
	return;
}

void TopFr::OnSaveAs(wxCommandEvent& WXUNUSED(event))
{
	FDial = new wxFileDialog(this, "Save As:", "My Computer", "rawr.rawr", "*.*", wxSAVE);
	FDial->ShowModal();
}

void TopFr::OnLoad(wxCommandEvent& WXUNUSED(event))
{
	FDial = new wxFileDialog(this, "Load:", "My Computer", "rawr.rawr", "*.*", wxOPEN);
	FDial->ShowModal();
}
Topframe.h:

Code: Select all

#include "IDs.h"

class MyApp: public wxApp
{
	virtual bool OnInit();
};

class TopFr: public wxFrame
{
public:
 
    TopFr(const wxString& title, const wxPoint& pos, const wxSize& size);

    void OnQuit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
	void OnPick(wxCommandEvent& event);
	void OnSave(wxCommandEvent& event);
	void OnSaveAs(wxCommandEvent& event);
	void OnLoad(wxCommandEvent& event);

	wxFileDialog *FDial;

	//static wxString wxMPN;

	//DECLARE_NO_COPY_CLASS(MyApp)
    DECLARE_EVENT_TABLE()
};

#include "TopFrameEvents.h"
Listctrl.cpp:

Code: Select all

#include "wx/wx.h"
#include "wx/listctrl.h"
#include "ListCTRL.h"

void LCtrl::Insert(wxListEvent& event)
{
	wxMessageBox("Insert", "rawr", wxOK, this);
}

void LCtrl::Delete(wxListEvent& event)
{
	wxMessageBox("Delete", "rawr", wxOK, this);
}
Listctrl.h:

Code: Select all

//#include "IDs.h"
#include "wx/wx.h"
#include "wx/listctrl.h"

class LCtrl: public wxListCtrl
{
public:
	const LCtrl(wxWindow *parent,
               const wxWindowID id,
               const wxPoint& pos,
               const wxSize& size,
               long style)
        : wxListCtrl(parent, id, pos, size, style),
          _Attr(*wxBLUE, *wxLIGHT_GREY, wxNullFont)
        {
        }

	void Insert(wxListEvent &event);
	void Delete(wxListEvent &event);

	//static LCtrl *Lctrl;
	//static LCtrl *Lctrl;
	//DECLARE_EVENT_TABLE()

private:
	wxListItemAttr _Attr;

	//DECLARE_NO_COPY_CLASS(LCtrl)
	DECLARE_EVENT_TABLE()
};

/*enum
{
	LIST_CTRL = 3124,
};*/

#include "ListCTRLEvents.h"
Topframeevents.h:

Code: Select all

BEGIN_EVENT_TABLE(TopFr, wxFrame)
    EVT_MENU(ID_Quit, TopFr::OnQuit)
    EVT_MENU(ID_About, TopFr::OnAbout)
	EVT_MENU(ID_Pick, TopFr::OnPick)
	EVT_MENU(ID_Save, TopFr::OnSave)
	EVT_MENU(ID_SaveAs, TopFr::OnSaveAs)
	EVT_MENU(ID_Load, TopFr::OnLoad)
END_EVENT_TABLE()
Listctrlevents.h:

Code: Select all

BEGIN_EVENT_TABLE(LCtrl, wxListCtrl)
	EVT_LIST_INSERT_ITEM(LIST_CTRL, LCtrl::Insert)
	EVT_LIST_DELETE_ITEM(LIST_CTRL, LCtrl::Delete)
END_EVENT_TABLE()
IDs.h:

Code: Select all

enum
{
    ID_Quit = 1,
    ID_About,
	ID_Pick,
	ID_Save,
	ID_SaveAs,
	ID_Load,

	/*LIST_Delete = 1000,
	LIST_Insert,*/
	LIST_CTRL = 3124,
};
There's a bunch of messageboxes because that's what I've inserted just so I can see that things are working untill I get around to coding that particular section.

The list control is a bit bare, as I was just trying to get it to work, then expand it, this may be the source of the problem, too.

Thanks for the time.
Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

That should be the other way around.
Well spotted leio, that will teach me to post first thing in the morning. :D

Try this and see if it makes a difference.

on the first line of Topframe.h add the following two lines

Code: Select all

#ifndef TOPFRAME_H
#define TOPFRAME_H
and at the end of Topframe.h add the line

Code: Select all

#endif
on the first line of Listctrl.h add the following two lines

Code: Select all


#ifndef LISTCTRL_H
#define LISTCTRL_H
and at the end of Listctrl.h add the line

Code: Select all

#endif
I'm sure you can see the pattern here, repeat for

Topframeevents.h
Listctrlevents.h
IDs.h

These defines ensure that the code in your header files only gets declared once and that stops you getting multiple declaration errors from the compiler.

Sof.T
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

Post by bugmenot »

Same deal :(
Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

Now you've altered the header files, you might need to rebuild the whole project.

I guess you are using Visual C++ or microsoft compiler which I am unfamiliar with. But there should be a rebuild all, or clean/rebuild option.

Try that and see what happens.

Sof.T
Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

Yet another post :wink:

I wonder why in Topframe.cpp you include listctrl.cpp, not listctrl.h. It should be the other way round.

Sof.T
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

Post by bugmenot »

Sof_T wrote:Now you've altered the header files, you might need to rebuild the whole project.

I guess you are using Visual C++ or microsoft compiler which I am unfamiliar with. But there should be a rebuild all, or clean/rebuild option.

Try that and see what happens.

Sof.T
I cleaned the solution and the project itself, no dice.
They seem to be talking about multiple included libraries, but any wx program other than this one I've written runs just fine, and I'm using the same base project for all of them.
Yet another post

I wonder why in Topframe.cpp you include listctrl.cpp, not listctrl.h. It should be the other way round.

Sof.T
I've seen it go both ways so I didn't think it mattered, does it beyond preference?

Again, thanks for the help, as this is probably pretty much off topic here.
Sof_T
Can't get richer than this
Can't get richer than this
Posts: 864
Joined: Thu Jul 28, 2005 9:48 pm
Location: New Forest, United Kingdom

Post by Sof_T »

Yet another post

I wonder why in Topframe.cpp you include listctrl.cpp, not listctrl.h. It should be the other way round.

Sof.T
I've seen it go both ways so I didn't think it mattered, does it beyond preference?
I think it does matter the reason why is that the preprocessor will see the code in listctrl.cpp and add it to the code in Topframe.cpp. Then the compiler will compile the code in listctrl.cpp and the same code in topframe.cpp. When the linker tries to combine the code it finds duplicates because it has compiled the same code twice and dosn't know which function of the two identical functions it should use.

Sof.T
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

Post by bugmenot »

Yaaay, it works!

But only if I copy listctrl.cpp's contents into the end of .h, otherwise it'll say my list control doesn't exist, blah blah, etc. How does I go about fixing this?
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Sounds like you don't link ListCTRL.o. You did add it to the project's files list, didn't you?
If it still fails, please post the complete compiler output.
this->signature=NULL;
bugmenot
Knows some wx things
Knows some wx things
Posts: 25
Joined: Wed Feb 02, 2005 1:59 am

Post by bugmenot »

I believe Visual Studio does this for me. Am I wrong?
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

I don't use Visual Studio, so I don't know. But if the compiler/linker complains about unknown symbols unless you directly include the .cpp (which btw. you should never do!) it sounds like it's not linked like it should be.
Please post the compiler/linker output so we can be sure.
this->signature=NULL;