C++ Error LNK2005 – item already defined in file.obj
Linker errors (LNK) can be a bit more difficult to solve than standard C errors if you don’t know how to read the error output. This is added to by the fact that you can’t double-click the error and be taken to the line causing the problem (if using Visual Studio anyway), so being able to read the error output will very much improve your chances of successfully debugging linker errors.
LNK2005 is very similar to error C2011 in so much as it refers to code which is being redefined. Whereas C2011 refers to class types being redefined, LNK2005 refers to method calls which may be redefined through the use of namespaces.
Error LNK2005 – Method already defined in Object.obj
What is it? | Error LNK2005 alerts you to code which is being defined multiple times. |
Common causes | LNK2005 can be caused by calling the same namespace in multiple files. See the example cause below for a demonstration of how this may occur. |
How to fix it? | This error can be fixed by using anonymous namespaces for common functionality. For example, if you have a method in a namespace to convert a C# Guid to C++ GUID being called in multiple places (i.e. perhaps your engine has multiple CLI Wrappers for different GUIs) then you can fix LNK2005 by making the namespace anonymous. See the example fix below for a demonstration. |
Example cause
As already mentioned, the common cause of this error is using methods that have already been defined by compiling other files.
namespace foo { ToGUID(Guid g) { array^ guidData = guid.ToByteArray(); pin_ptr data = &(guidData[ 0 ]); return *(_GUID *)data; }; };
#using foo class bar { GUID g = ToGUID(inG); };
#using foo class boo { GUID g = ToGUID(inG); };
When bar is compiled everything will be fine as there won’t be a definition of the foo namespace to begin with, however, when boo is then compiled the linker will complain that ToGUID is already defined in bar.obj – causing LNK2005
Example fix
The quickest fix for this error is to make the namespace anonymous by not giving it a name. This prevents the foo namespace from trying to be defined more than once, because the namespace now has no name. This is done as follows:
namespace { //Note the lack of a name here ToGUID(Guid g) { array^ guidData = guid.ToByteArray(); pin_ptr data = &(guidData[ 0 ]); return *(_GUID *)data; }; };