[SOLVED]Linking Error

Get answers to all your basic programming questions. No Ogre questions, please!
mamairaja
Halfling
Posts: 60
Joined: Fri Dec 25, 2009 3:31 pm

[SOLVED]Linking Error

Post by mamairaja »

hello

I have a Heightfunction.h file included in Gloader.cpp and Gloader1.cpp.
In both cpps I have this code

Code: Select all

HeightFunction::initialize(gameEngineData->mSceneMgr);
treeLoader->setHeightFunction(&HeightFunction::getTerrainHeight);
It compiles fine and when link I am getting this error
1>GLoader1.obj : error LNK2005: "bool HeightFunction::initialized" (?initialized@HeightFunction@@3_NA) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::RaySceneQuery * HeightFunction::raySceneQuery" (?raySceneQuery@HeightFunction@@3PAVRaySceneQuery@Ogre@@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class HeightFunction::MyRaySceneQueryListener * HeightFunction::raySceneQueryListener" (?raySceneQueryListener@HeightFunction@@3PAVMyRaySceneQueryListener@1@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::Ray HeightFunction::updateRay" (?updateRay@HeightFunction@@3VRay@Ogre@@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "void __cdecl HeightFunction::initialize(class Ogre::SceneManager *)" (?initialize@HeightFunction@@YAXPAVSceneManager@Ogre@@@Z) already defined in GLoader.obj
1>bin\Release\TheGameProject.exe : fatal error LNK1169: one or more multiply defined symbols found

hiehgtfunction.h has following code

Code: Select all

#ifndef HEIGHTFUNCTION_H
#define HEIGHTFUNCTION_H


#include "Ogre.h"
using namespace Ogre;

namespace HeightFunction
{
	class MyRaySceneQueryListener: public RaySceneQueryListener
	{
	public:
		inline bool queryResult(SceneQuery::WorldFragment *fragment, Ogre::Real distance)
		{
			resultDistance = distance;
			return false;
		}
		inline bool queryResult(MovableObject *obj, Ogre::Real distance)
		{
			resultDistance = distance;
			return false;
		}

		float resultDistance;
	};

	bool initialized = false;
	Ogre::RaySceneQuery* raySceneQuery;
	Ogre::Ray updateRay;
	MyRaySceneQueryListener *raySceneQueryListener;

	//Initializes the height function. Call this before calling getTerrainHeight()
	void initialize(SceneManager *sceneMgr){
		//if (!initialized){
			initialized = true;
			updateRay.setOrigin(Vector3::ZERO);
			updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
			raySceneQuery = sceneMgr->createRayQuery(updateRay);
			raySceneQuery->setQueryTypeMask(Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);   
			raySceneQuery->setWorldFragmentType(Ogre::SceneQuery::WFT_SINGLE_INTERSECTION); 
			raySceneQueryListener = new MyRaySceneQueryListener;
		//}
	}

	//Gets the height of the terrain at the specified x/z coordinate
	//The userData parameter isn't used in this implementation of a height function, since
	//there's no need for extra data other than the x/z coordinates.
	inline float getTerrainHeight(const float x, const float z, void *userData = NULL){
		updateRay.setOrigin(Vector3(x, 0.0f, z));
		updateRay.setDirection(Vector3::UNIT_Y);
		raySceneQuery->setRay(updateRay);
		raySceneQuery->execute(raySceneQueryListener);

		return raySceneQueryListener->resultDistance;
	}
}

#endif
Could you please tell me what to do for this error?
Last edited by mamairaja on Sat May 15, 2010 5:28 pm, edited 1 time in total.
User avatar
MrD
Goblin
Posts: 292
Joined: Wed Oct 21, 2009 3:16 pm
Location: England
x 1

Re: Linking Error

Post by MrD »

You've added a function outside of a class, defined in the header file that isn't marked as inline so is getting defined in multiple classes when it is compiled.
void initialize(SceneManager *sceneMgr)

Either:
  • Mark that function as inline
  • Create a HeightFunction.cpp file and move the definition of that function in there, and change the code in HeightFunction.h to just be a declaration
Insimnax Framework - A game framework for OGRE
mamairaja
Halfling
Posts: 60
Joined: Fri Dec 25, 2009 3:31 pm

Re: Linking Error

Post by mamairaja »

Thank you for the reply.
Sorry I am still getting the error.

new header file

Code: Select all

#ifndef HEIGHTFUNCTION_H
#define HEIGHTFUNCTION_H


#include "Ogre.h"
using namespace Ogre;

namespace HeightFunction
{
	class MyRaySceneQueryListener: public RaySceneQueryListener
	{
	public:
		inline bool queryResult(SceneQuery::WorldFragment *fragment, Ogre::Real distance);
		inline bool queryResult(MovableObject *obj, Ogre::Real distance);
		float resultDistance;
	};

	bool initialized = false;
	Ogre::RaySceneQuery* raySceneQuery;
	Ogre::Ray updateRay;
	MyRaySceneQueryListener *raySceneQueryListener;

	inline void initialize(SceneManager *sceneMgr);	
	inline float getTerrainHeight(const float x, const float z, void *userData = NULL);
}

#endif
cpp

Code: Select all

#include "HeightFunction.h"

namespace HeightFunction
{
	inline bool MyRaySceneQueryListener::queryResult(SceneQuery::WorldFragment *fragment, Ogre::Real distance)
	{
		resultDistance = distance;
		return false;
	}

	inline bool MyRaySceneQueryListener::queryResult(MovableObject *obj, Ogre::Real distance)
	{
		resultDistance = distance;
		return false;
	}

	inline void initialize(SceneManager *sceneMgr)
	{
			initialized = true;
			updateRay.setOrigin(Vector3::ZERO);
			updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
			raySceneQuery = sceneMgr->createRayQuery(updateRay);
			raySceneQuery->setQueryTypeMask(Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);   
			raySceneQuery->setWorldFragmentType(Ogre::SceneQuery::WFT_SINGLE_INTERSECTION); 
			raySceneQueryListener = new MyRaySceneQueryListener;
		
	}

	inline float getTerrainHeight(const float x, const float z, void *userData)
	{
		updateRay.setOrigin(Vector3(x, 0.0f, z));
		updateRay.setDirection(Vector3::UNIT_Y);
		raySceneQuery->setRay(updateRay);
		raySceneQuery->execute(raySceneQueryListener);

		return raySceneQueryListener->resultDistance;
	}
}
error message
1>Linking...
1>GLoader1.obj : error LNK2005: "bool HeightFunction::initialized" (?initialized@HeightFunction@@3_NA) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::RaySceneQuery * HeightFunction::raySceneQuery" (?raySceneQuery@HeightFunction@@3PAVRaySceneQuery@Ogre@@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class HeightFunction::MyRaySceneQueryListener * HeightFunction::raySceneQueryListener" (?raySceneQueryListener@HeightFunction@@3PAVMyRaySceneQueryListener@1@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::Ray HeightFunction::updateRay" (?updateRay@HeightFunction@@3VRay@Ogre@@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "bool HeightFunction::initialized" (?initialized@HeightFunction@@3_NA) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class Ogre::RaySceneQuery * HeightFunction::raySceneQuery" (?raySceneQuery@HeightFunction@@3PAVRaySceneQuery@Ogre@@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class HeightFunction::MyRaySceneQueryListener * HeightFunction::raySceneQueryListener" (?raySceneQueryListener@HeightFunction@@3PAVMyRaySceneQueryListener@1@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class Ogre::Ray HeightFunction::updateRay" (?updateRay@HeightFunction@@3VRay@Ogre@@A) already defined in GLoader.obj
1>GLoader.obj : error LNK2001: unresolved external symbol "float __cdecl HeightFunction::getTerrainHeight(float,float,void *)" (?getTerrainHeight@HeightFunction@@YAMMMPAX@Z)
1>GLoader.obj : error LNK2001: unresolved external symbol "void __cdecl HeightFunction::initialize(class Ogre::SceneManager *)" (?initialize@HeightFunction@@YAXPAVSceneManager@Ogre@@@Z)
1>bin\Release\TheGameProject.exe : fatal error LNK1120: 2 unresolved externals
User avatar
MrD
Goblin
Posts: 292
Joined: Wed Oct 21, 2009 3:16 pm
Location: England
x 1

Re: Linking Error

Post by MrD »

Seriously, I give you two choices and you somehow manage to do both of them.

Remove the 'inline' keyword from everything, since they are certainly no longer inline since they are in a separate file. If you still get the linker error after that, try doing a full rebuild, if that still fails, get back to me.
Insimnax Framework - A game framework for OGRE
mamairaja
Halfling
Posts: 60
Joined: Fri Dec 25, 2009 3:31 pm

Re: Linking Error

Post by mamairaja »

Thank you
Still getting the error.
I have simplified the code
Now the header is

Code: Select all

#ifndef HEIGHTFUNCTION_H
#define HEIGHTFUNCTION_H

#include "MyRaySceneQueryListener.h"

namespace HeightFunction
{
	bool initialized = false;
	Ogre::RaySceneQuery* raySceneQuery;
	Ogre::Ray updateRay;
	MyRaySceneQueryListener *raySceneQueryListener;

	void initialize(SceneManager *sceneMgr);	
	float getTerrainHeight(const float x, const float z, void *userData = NULL);
}

#endif
cpp

Code: Select all

namespace HeightFunction
{
	void initialize(SceneManager *sceneMgr)
	{
			initialized = true;
			updateRay.setOrigin(Vector3::ZERO);
			updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
			raySceneQuery = sceneMgr->createRayQuery(updateRay);
			raySceneQuery->setQueryTypeMask(Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);   
			raySceneQuery->setWorldFragmentType(Ogre::SceneQuery::WFT_SINGLE_INTERSECTION); 
			raySceneQueryListener = new MyRaySceneQueryListener;
		
	}

	float getTerrainHeight(const float x, const float z, void *userData)
	{
		updateRay.setOrigin(Vector3(x, 0.0f, z));
		updateRay.setDirection(Vector3::UNIT_Y);
		raySceneQuery->setRay(updateRay);
		raySceneQuery->execute(raySceneQueryListener);

		return raySceneQueryListener->resultDistance;
	}
}

Follwoing code in both Gloader.cpp and Gloader1.cpp

Code: Select all

#include "HeightFunction.h"
HeightFunction::initialize(gameEngineData->mSceneMgr);
treeLoader->setHeightFunction(&HeightFunction::getTerrainHeight);
Cleaned and built
The error I am getting
1>Linking...
1>GLoader1.obj : error LNK2005: "bool HeightFunction::initialized" (?initialized@HeightFunction@@3_NA) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::RaySceneQuery * HeightFunction::raySceneQuery" (?raySceneQuery@HeightFunction@@3PAVRaySceneQuery@Ogre@@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class MyRaySceneQueryListener * HeightFunction::raySceneQueryListener" (?raySceneQueryListener@HeightFunction@@3PAVMyRaySceneQueryListener@@A) already defined in GLoader.obj
1>GLoader1.obj : error LNK2005: "class Ogre::Ray HeightFunction::updateRay" (?updateRay@HeightFunction@@3VRay@Ogre@@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "bool HeightFunction::initialized" (?initialized@HeightFunction@@3_NA) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class Ogre::RaySceneQuery * HeightFunction::raySceneQuery" (?raySceneQuery@HeightFunction@@3PAVRaySceneQuery@Ogre@@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class MyRaySceneQueryListener * HeightFunction::raySceneQueryListener" (?raySceneQueryListener@HeightFunction@@3PAVMyRaySceneQueryListener@@A) already defined in GLoader.obj
1>HeightFunction.obj : error LNK2005: "class Ogre::Ray HeightFunction::updateRay" (?updateRay@HeightFunction@@3VRay@Ogre@@A) already defined in GLoader.obj
1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
1>bin\Release\TheGameProject.exe : fatal error LNK1169: one or more multiply defined symbols found
mamairaja
Halfling
Posts: 60
Joined: Fri Dec 25, 2009 3:31 pm

Re: Linking Error

Post by mamairaja »

Code: Select all

bool initialized = false;
Ogre::RaySceneQuery* raySceneQuery;
Ogre::Ray updateRay;
MyRaySceneQueryListener *raySceneQueryListener;
Bring the above code to heightfunction.cpp

Code: Select all

#include "HeightFunction.h"

namespace HeightFunction
{
	bool initialized = false;
	Ogre::RaySceneQuery* raySceneQuery;
	Ogre::Ray updateRay;
	MyRaySceneQueryListener *raySceneQueryListener;

	void initialize(SceneManager *sceneMgr)
	{
			initialized = true;
			updateRay.setOrigin(Vector3::ZERO);
			updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y);
			raySceneQuery = sceneMgr->createRayQuery(updateRay);
			raySceneQuery->setQueryTypeMask(Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK);   
			raySceneQuery->setWorldFragmentType(Ogre::SceneQuery::WFT_SINGLE_INTERSECTION); 
			raySceneQueryListener = new MyRaySceneQueryListener;
		
	}

	float getTerrainHeight(const float x, const float z, void *userData)
	{
		updateRay.setOrigin(Vector3(x, 0.0f, z));
		updateRay.setDirection(Vector3::UNIT_Y);
		raySceneQuery->setRay(updateRay);
		raySceneQuery->execute(raySceneQueryListener);

		return raySceneQueryListener->resultDistance;
	}
}
Now it works fine, no error.
Cannot understand what has really happens, could you please explain bit
And what this inline function really means?
User avatar
MrD
Goblin
Posts: 292
Joined: Wed Oct 21, 2009 3:16 pm
Location: England
x 1

Re: Linking Error

Post by MrD »

Ah of course *smacks head* I forgot you had variables inside your header file, yeah, that would cause that.

If you need those variables to be available in other places besides HeightFunction.cpp, then you can either make them static or extern, if you just need to use them in the cpp file then it's fine to leave them as they are.

Basically, when you include a file anywhere in code, all the C++ pre-processor does is dump the contents of that file into the file you included it in, this means that anything like variables and functions that are defined in the header file get copied into multiple compilation units, so when the linker tries to link it finds multiple versions of the same thing, and gets confused.

You can get around this by marking variables as static or extetn (look up on Google for the difference, I would explain but I have to leave in 5 minutes), and by either marking functions defined in a header to be inline or static, or by separating the function so that just the declaration is inside the header, and the definition is inside another cpp file.
Insimnax Framework - A game framework for OGRE
mamairaja
Halfling
Posts: 60
Joined: Fri Dec 25, 2009 3:31 pm

Re: Linking Error

Post by mamairaja »

Thank you very much MrD
Basically, when you include a file anywhere in code, all the C++ pre-processor does is dump the contents of that file into the file you included it in, this means that anything like variables and functions that are defined in the header file get copied into multiple compilation units, so when the linker tries to link it finds multiple versions of the same thing, and gets confused.
Now I have better understand of what really happened.

I have tried both static and extern. For static it works fine but extern still make the same error.

The origninal problem solved.
Josephmin
Gnoblar
Posts: 3
Joined: Sat Jul 14, 2012 4:34 pm

Re: [SOLVED]Linking Error

Post by Josephmin »

Hello !

Code: Select all


1>Game.obj : error LNK2001: "float __cdecl HeightFunction::getTerrainHeight(float,float,void *)" (?getTerrainHeight@HeightFunction@@YAMMMPAX@Z)
1>Game.obj : error LNK2001: "void __cdecl HeightFunction::initialize(class Ogre::SceneManager *)" (?initialize@HeightFunction@@YAXPAVSceneManager@Ogre@@@Z)

It seems some Linking Error For HeightFunction, Can you Help me solve it ?

Thank you very much!