Namespace function linker error when used in multiple classes - c++

I am simply writing a function that I want to use in my code for debugging WITHOUT throwing exceptions. I want a defined variable DEBUG_MODE that when set to true causes the function to print a given message and when set to false prints nothing. I want it available to any class that imports the file without having to create a class, i.e. I include "Debug.h" and can call Debug::Log(string message).
I read about the advantages of using namespace functions so I wrote it as such but perhaps I don't understand the proper usage of namespace functions. When I include my header file with the namespace function in one class it works great, when I use it in two classes in two different files I get a linker error:
Error 1 error LNK2005: "void __cdecl Debug::Log(char const *)" (?Log#Debug##YAXPBD0#Z) already defined in Foo.obj...
Here is the code for my namespace functions:
#pragma once
#include <cstdio>
// IMPORTANT: Set this to true if you want debug logging, false otherwise
#define DEBUG_MODE true
namespace Debug
{
void Log(const char* message)
{
if (DEBUG_MODE)
printf(message);
}
void Log(const char* messageFormat, const char* parameter)
{
if (DEBUG_MODE)
printf(messageFormat, parameter);
}
}
Now if I make the functions static then everything works fine, but I was under the impression that using namespace functions was the alternative to static functions in my case. I would also like to be able to define static functions in another file if possible.
What should I use? A static function? A namespace function? If the latter then how do I use namespace functions in two separate classes/files without causing the above linker error?

All you are missing is the inline keyword like so:
inline void Log(const char* message)
Without inline, the functions are created for each source file including your header file.
static would have a similar outcome, but inlining seems preferred for such a small functions.
Or, if you don't want to make the compiler create the code again and again in all files, you of course need to have the implementation just once in one .cpp file and leave just the declaration in the header.
In order for the DEBUG_MODE to affect it, though, you will need to do it e.g. like this:
#ifndef DEBUG_MODE
// Dummy implementation
inline void Log(...) {}
#else
// Implemented in Log.cpp
void Log(const char* message);
void Log(const char* messageFormat, const char* parameter);
#endif

Try making them inline. Otherwise you could define them in a separate source file and just declare them in the header file.
If you define it in the header as a non-inline non-static function and include it in more than one source file of a program, the linker will be presented with copies of the same function in multiple object files.
There are 3 solutions:
Make them inline.
Make them static.
Define them in their own source file and only declare them in the
header file.
Making them static causes the names not to be exported and they are therefore only known inside one object file. But you will still have multiple copies of the functions, but only one copy each in each object file that uses them.

Related

Include h-file with definitions inside in multiple cpp-files [duplicate]

This question already has answers here:
Writing function definition in header files in C++
(6 answers)
Closed 2 years ago.
My problem is that I have header-file (custom unit-test framework) with function definitions in it. For example:
unit_test.h:
#pragma once
...
void Assert(bool b, const string& hint = {})
{
AssertEqual(b, true, hint);
}
...
it's convenient for me to keep some functions defined right in the header, because I often use this functional by simply including (unit_test.h is located in separate directory C:/Dev/include). But if I am dealing with a project where multiple cpp files use this functionality, I get a multiple definition error as expected.
Simple project looks like:
main.cpp:
#include "unit_test.h"
void foo();
int main()
{
Assert(1);
foo();
return 0;
}
foo.cpp:
#include "unit_test.h"
void foo()
{
Assert(2);
}
So I want to know if there is a right way to keep function definitions in a header file and use it in project without getting an multiple definition error? (Or would it be better to move the function definitions to the source and compile it separately each time, or compile unit_test into a static library?)
Easiest way to achieve it, is to add inline keyword in function definiton, but it's not a best solution.
Best option is to move definition to source file, but only it it's not a template.
I would use anonymous namespace with inline:
namespace {
inline void Assert(bool b, const string& hint = {})
{
AssertEqual(b, true, hint);
}
}
This error is beacuse whenever you will include the file it will define the function again. The solution is make a header file unit_test.h with declaration only and create a source file unit_test.cpp for definition. Now you can include header file it will not give error. Don't forget to add #ifndef in header as follow
unit_test.h
#ifndef UNIT_TEST_H_
#define UNIT_TEST_H_
// Declare you function
// and end with:
#endif

How to import a C function into C++ project that has not been declared in a C header?

I'm trying to include some functions written in C into a C++ project. I've come quite far following these instructions.
Unfortunately not all of the C functions I require to call are declared in a c header file. Some are just static functions defined inside the ".c-files".
Is there a way to still call such "non-declared-C-functions" from inside a class of my C++ project without altering the C sources (which are not maintained by myself)?
I already thought about forward declaring the C function myself in my C++ header like this:
extern "C"
{
#include "c_header_1.h"
static void c_function(int* out, const unsigned char len, const some_c_struct* st);
#include "c_header_2.h
}
gcc only reports an error:
warning: void c_function(int*, const unsigned char, const some_c_struct*); declared static but never defined [-Wunused-function].
The pointer to struct passed as 3rd parameter to c_function(int*, const unsigned char, const some_c_struct*) seems to make things even more tricky, since that type some_c_struct is declared inside the header belonging to the ".c-file" c_function(...) is declared in as well. This means I need to include the header before the forward declaration of c_function(...) but apparently this makes the linker oversee the definition.
A very simplyfied version of the C++ code looks roughly this:
Header File "CppClass.h":
#ifndef CPP_CLASS_H
#define CPP_CLASS_H
extern "C"
{
#include "c_header_1.h"
#include "c_header_2.h"
...
}
class CppClass
{
public:
//...
void some_member();
//...
};
#endif
Implementation "CppClass.cpp"
//...
void CppClass::some_member()
{
//...
::c_func_x(32, &data); // call to function in c_header_1
//...
::c_func_y(&data2); // call to function in c_header_2
::c_function(data3, len, st);
}
Clean answer: No. Functions declared static in a translation unit (.c or .cpp files typically) are not accessible anywhere else, even if you forward declare the correct function signature.
Messy answer, would not recommend: #include the offending .c file into your .cpp file and see if it works. I would consider this a hack though. Implementation files contain exactly what the name implies: implementations, not interfaces. This typically implies that you are not supposed to know about what is going on inside of it and that it might change between versions.
If you know the guy who is maintaining the sources, you could also try contacting him and ask if he could make the function part of the public interface, i.e. put it in a header and make it non-static.
I suggest that you copy the functions into a new file. Make them not static. Make a header file for them, and include that in your cpp.

Compiler complains about redefinition even with guards present

I'm trying to set up some logging functions for an OpenGL application. GLFW offers the option to register a callback function that is called whenever an error takes place, but because it is a C library it demands that the function be written in C style, i.e. outside of a class. Because of that, I put my logging functions into a namespace defined in file log.h.
#ifndef LOG_H
#define LOG_H
#include <fstream>
namespace gllog{
#define GL_LOG_FILE "gl.log"
bool restart_gl_log(){
//...
}
bool gl_log (const char* message, const char* filename, int line){
//...
}
void glfw_error_callback (int error, const char* description){
//...
}
};
#endif
Even though I added include guards, whenever I include this file from two different files, I get errors like the following:
CMakeFiles/gl4tuts.dir/extended_initialisation/ExtendedInitialisation.cpp.o: In function `gllog::glfw_error_callback(int, char const*)':
ExtendedInitialisation.cpp:(.text+0x340): multiple definition of `gllog::glfw_error_callback(int, char const*)'
CMakeFiles/gl4tuts.dir/hello_triangle/HelloTriangle.cpp.o:HelloTriangle.cpp:(.text+0xa10): first defined here
I'm building with CMake.
What could be the reason? Could the absence of a class be related?
Include guards protect you from including the same header file more than once while compiling the same .cpp file. They don't stop you from including the same header file more than once while compiling different .cpp files -- in fact they're commonly used to make the same class available in different compilation units.
The compiler is not complaining, by the way, the linker is.

Trying to create an error log ofstream -- getting "one or more multiply defined symbols found"

I'm trying to do this:
#pragma once
#include <fstream>
#include <string>
static std::ofstream ErrorLog;
void InitErrorLog(std::string FileName) {
ErrorLog.open(FileName);
}
but am getting a "One or more multiply defined symbols found" error when #include-ing in multiple CPP files. What is the STL doing (to provide cout, cin, cerr, etc. -- this approach originates as an alternative to redirecting cerr) that I'm not?
You are providing the definition for ErrorLog in a header file. Instead, define it in a source file and leave an extern declaration at the header.
source
std::ofstream ErrorLog;
void InitErrorLog(std::string FileName) {
ErrorLog.open(FileName);
}
header
extern std::ofstream ErrorLog;
void InitErrorLog(std::string FileName);
Additionaly, in order to keep your function at the header you have to make it inline.
You're breaking the one definition rule. You need to make the method inline.
inline void InitErrorLog(std::string FileName) {
ErrorLog.open(FileName);
}
Also, note that by declaring your variable static, you'll have a copy per translation unit - i.e. it's not a global. To make it global, you need to declare it extern in the header and define it in a single implementation file.

C++ Where to define globals (Linker Error: Symbol already defined)

I googled for about 30 minutes now and didnt find anything related to my problem:
I use Visual Studio C++ 2008, it declared a header for me called "stdafx.h"
in this header i declared all stuff i need, an i want the global variables to be in there too, but when i want to use one of these variables, i get an error (at compiling time)
my "stdafx.h" looks like this:
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
windows header here....
// C RunTime Header Files
compiler related standard headers here....
// TODO: reference additional headers your program requires here
#ifndef aaab
#include "codename.hpp"
#define aaab
#endif
// and a load of other headers (all of my project) followed here
...
...
...
and after the declarations i defined my globals like:
Game *game;
and i want to use them in "codename.cpp"
here a short view of the class
#include "stdafx.h"
#define MAX_LOADSTRING 100
other class related stuff here....
main function here....
void test()
{
game = new Game(); // HERE IS THE ERROR
}
You probably need to declare your global as extern in the header file:
extern Game *game;
Then define it in a .cpp file.
Here are some methods to handle global variables:
Define in separate namespace
Cluster into a static class
Static source with accessor functions
Define in global namespace
In any situation, the preferred method is to declare the variable in a header file and define it in a source file.
Separate Namespace
This is better than a variable declared in the global namespace since it reduces the likelihood of collision with other variables and reduces contamination by other functions.
Example:
namespace Math_Globals
{
int a_math_int;
}
Clustered in static class
Other languages don't allow global variables so they must be clustered into a class. Making them static inside a class and the class static provides for only one instance. Similar to a singleton pattern.
This design allows you to cluster your globals and provides more protection against collision and unauthorized access. The more difficult to access the variable, the less likely a programmer is to use it (and provide collision & unauthorized access).
Example:
static class Math_Globals
{
public:
static int math_global; // Declaration.
};
int Math_Globals::math_global; // This is how it would be defined.
Static in module with accessor functions
A common safeguard in the C language is to define the variable static in a source module and provide public accessor functions. This allows for some access control.
Example:
Header.hpp:
int Get_Math_Global(void);
void Set_Math_Global(int new_value);
Source.cpp:
static int my_math_global = INITIAL_VALUE;
int Get_Math_Global(void)
{
return my_math_global;
}
void Set_Math_Global(int new_value)
{
my_math_global = new_value;
return;
}
Global Namespace
The consensus among programmers is that variables defined in the global namespace is evil. Some say that any of the above methods (or other methods) is preferred.
Global variables may lead to strongly coupled functions and modules which are difficult to reuse. Also in debugging, finding the function that changed the variable's state to an unexpected value is difficult, or time consuming.
You are declaring a global variable named ggg on a header, included from two or more .cpp.
Global variables should only be declared on a .cpp, and optionally defined as external on an .h.
Solution:
Find the ggg declaration.
Add the extern keyword before it.
Create a new global variable on a .cpp named ggg.