0

I've hit a roadblock in attempting to integrate some third-party code in my project. I'm attempting to integrate fontstash, which is a header-only OpenGL text rendering solution. (https://github.com/memononen/fontstash) As a whole, I'm also using SDL, GLEW, AssImp, Lua 5.3/LuaBridge, and Bullet Physics. I've placed the fontstash header files in my vc/include directory. Compilation proceeds normally but linking fails miserably in a huge wall of...

c_main.obj : error LNK2005: "unsigned int __cdecl glfonsRGBA(unsigned char,unsigned char,unsigned char,unsigned char)" (?glfonsRGBA@@YAIEEEE@Z) already defined...
c_main.obj : error LNK2005: "void __cdecl glfonsDelete(struct FONScontext *)" (?glfonsDelete@@YAXPAUFONScontext@@@Z) already defined in...
...
c_main.obj : error LNK2005: _stbtt_FindMatchingFont already defined in...
c_main.obj : error LNK2005: _stbtt_GetFontNameString already defined...

It appears to simply iterate the entire list of functions provided via the fontstash header files. I've tried wrapping the headers in an extern "C" {} to no avail. I've tried including the files from the project directory as well. I'm at a loss as to why this would be happening and where to begin figuring out what would be causing it. As indicated in the topic title I'm using MSVC12/Win7, and I'm building for Windows and compiling for x86.

Additionally, I'm including the files more than once as the relevant code that utilizes fontstash is used in other locations. I've thought about this being the issue, but the provided header files from fontstash have inclusion guards so I fail to see why this would occur in that regard.

  • Clarifying that when I attempted using the header files from the project directory they were NOT in the vc/include directory at the time. – anfractu0us Mar 18 '16 at 05:07
  • would include guards help? https://en.wikipedia.org/wiki/Include_guard – mentat Mar 18 '16 at 05:25
  • The the header files already have as such: #ifndef FONS_H #define FONS_H but I didn't think about trying pragma, doing so now! – anfractu0us Mar 18 '16 at 05:28
  • Unfortunately doesn't alleviate the issue :( – anfractu0us Mar 18 '16 at 05:44
  • 1
    FYI, include guards are "reset" between translation units, so they don't work as you may intend when you have multiple source files. That said, your question is off topic, because it doesn't include the required minimal example. Extracting that should already give you a hint and make sure only the relevant influences remain. – Ulrich Eckhardt Mar 18 '16 at 05:52

1 Answers1

2

This is a common problem with the header files, that contain implementaton. When you use #include directive, compiler simply inserts .h file content instead of it. So when you use this header in different places of your project, you get several identical implementations of its methods and global variables. Since it has #ifdef or #pragma once compiler guard, it compiles just fine. But when linker is trying to unite all compiled obj files to one executable module, it gets several identical implementations. Since it could not know which one should be used, you get LNK2005 error. To solve this problem you could move implementations and globals into the separate cpp file and include it in the project. Other way would be to mark all header functions as inline, or use __declspec(selectany)

Ari0nhh
  • 5,720
  • 3
  • 28
  • 33
  • I had a feeling that I might have to do something along those lines; well, I know what I'm doing tomorrow anyway! :P Thanks. – anfractu0us Mar 18 '16 at 05:54