Compiler complains about redefinition even with guards present - c++

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.

Related

multiple definition error using namespace

I have created header file abc.hpp which contains a namespace of multiple functions.
When I use single source file which includes the header and call the function defined in namespace it works well, but when I call the same function in project where I have to include this header in multiple places, compilation gives me multiple definition error.
My other files are created as library and get executed.
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
namespace abc {
void sendtext(const char* msg)
{
create_context(mycontext);
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn)
{
create_context(mycontext);
send_context(create_context,msg, errn)
}
};
#endif
test.cpp:
#include"abc.hpp"
int main()
{
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
You can treat header files as if they are copy-pasted into your implementation files. So by putting function definitions into your headers, those definitions appear in multiple translation units (roughly, compiler .cpp files). This is not allowed - how is the compiler supposed to tell between them if they end up different?
Usually you would have a .h/.cpp pair, with function declarations going in the .h, and function definitions going in the .cpp. This way the definition only appears once in your whole program.
I can split your code like this:
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
// function **declarations**
namespace abc{
void sendtext(const char* msg);
void sendtextwitherrno(const char* msg, int errn);
}
#endif
abc.cpp:
#include "abc.hpp"
#include "context.hpp" // I guess this might be where create_context and send_context come from
// function **definitions**
namespace abc{
void sendtext(const char* msg){
create_context(mycontext); // not sure where mycontext is supposed to live?
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn){
create_context(mycontext);
send_context(create_context,msg, errn);
}
}
test.cpp:
#include "abc.hpp"
int main(){
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
Another way is to mark the functions as inline - this tells the compiler you are deliberately repeating the function definition all over the place, and you'd better be sure the definition is always identical. How sure are you? Are there different macros or different compiler flags in place in different places the function is used?

Multiple Errors When Compiling with g++?

When compiling my code, I'm receiving many different errors such as:
frame.h:5:48: error: expected identifier before '(' token
frame.h:5:17: error: variable or field 'writeFrame' declared void
frame.h:5:17: error: 'GifWriter' was not declared in this scope
frame.h:5:34: error: expected primary-expression before 'double'
These errors more or less apply for all the function parameters.
Here is the header file:
#ifndef frame_h
#define frame_h
void writeFrame(GifWriter* gptr, double delay, (std::vector<uint8_t>& frameOut), ImageData* image1ptr, struct Options mode, int frameNum, bool* runptr);
void runPRGM(ImageData* image1ptr, struct Options mode);
#endif
My .cpp file does include the required libraries and this .h file, and the two functions are declared in the same way. I'm certain the brackets and parentheses are parsed correctly. Other than the function definitions within the .cpp, these are the only instances of the functions' declarations.
What could I potentially be doing wrong? I did read in some other thread that g++ conflicts with certain void functions as well but there wasn't much elaboration on that.
Change (std::vector<uint8_t>& frameOut) to std::vector<uint8_t>& frameOut.
Not sure why you felt the need to put the brackets there, and the first error message is telling you that's the problem.
Also note that you should write header files so that they are self-contained. This means that this header file should have #include <vector> as well as having declarations for GifWriter etc. These may be forward declarations if the circumstances are right.
So the header should look something like this
#ifndef frame_h
#define frame_h
#include <vector> // for vector
#include <cstdint> // for uint8_t
class GifWriter; // forward declarations
class ImageData;
struct Options;
void writeFrame(GifWriter* gptr, double delay, std::vector<uint8_t>& frameOut, ImageData* image1ptr, Options mode, int frameNum, bool* runptr);
void runPRGM(ImageData* image1ptr, Options mode);
#endif
Image assuming that GifWriter, ImageData and Options are classes that you have written and therefore its safe to forward declare them. If not then you should include the header files for those classes here instead.

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.

Namespace function linker error when used in multiple classes

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.

Define the prototype of a function with a std::vector as input parameter in an header

I'm getting crazy since i'm not able to define the prototype of a function i'm actually using.
What i'm doing is create an header file called func1.hwhere i define this prototype (that's because i need to invoke this function from some other function implemented elsewhere):
void FileVector(std::vector<Files> &,const char*,bool);
Where Filesis a struct defined in func1.cpp
struct Files{
HANDLE h;
WIN32_FIND_DATA info;
} file;
I have also another function that accept a std::vector<Files> & as input parameter but when i try to compile (using Eclipse C++) i'm getting those errors:
/FileVector.h:11:22: error: variable or field 'FileVector' declared void
..\/FileVector.h:11:17: error: 'vector' is not a member of 'std'
..\/FileVector.h:11:29: error: 'Files' was not declared in this scope
I've tryied to include several directive in the header file..for example declaring the struct in the header and including vector header do the trick but this way i got loads of "multiple definitions/first defined here" error.
What can i do?
EDIT
Now my header looks like:
#ifndef FILEVECTOR_H_
#define FILEVECTOR_H_
#include <vector>
#include <windows.h>
struct Files{
HANDLE h;
WIN32_FIND_DATA info;
};
void FileVector(std::vector<Files> &,const char*,bool);
#endif /* FILEVECTOR_H_ */
At this point, i need to declare another prototype in another header:
void ProcessInput(vector<Files>&);
but i can't use the same trick as above cause i'll have to re-define the Files struct. How can i solve this?
Make sure to include <vector> in your header file. You also mention that the definition of Files is within the cpp file, you should move it to the header as well.
Also place proper header guards to avoid multiple definition errors:
#ifndef MY_HEADER_FILE_GUARD
#define MY_HEADER_FILE_GUARD
... your content here ...
#endif /*MY_HEADER_FILE_GUARD*/
Update:
Simply including filevector.h from your new header would do. However, it looks like Files should be defined in a header of its own and included from the two headers that make use of it.