I am working on a huge project which has one file A.h whose code has a line
typedef unsigned __int16 Elf64_Half;
Also since I am building on Linux and using dlinfo function, I have to include link.h file in my project. And this is where it creates a conflict because I have two typedefs having the same name Elf64_Half. (Linux link.h includes elftypes.h and it too has: typedef unsigned short Elf64_Half;).
What do I do in such a case? Is the only option I have, to change my typedef in a.h? Remember it is not too easy because the project is huge and I will have to make a change in several places.
Is there a way to undef a typedef or something?
For clarification, Rahul Manne gave an easy solution. Do
#define Elf64_Half The_Elf64_Half_I_dont_care
#include<link.h>
#undef Elf64_Half
#include<A.h>
/*
* Code here and use Elf64_Half from A.h as you like.
* However, you can't use Elf64_Half from link.h here
* or you have to call it The_Elf64_Half_I_dont_care.
*
*/
This will substitute each Elf64_Half in link.h with The_Elf64_Half_I_dont_care and thus you get no conflicts with A.h. As long as you don't want to use Elf64_Half of link.h explicitly that will work with no problems. You just have to remember that Elf64_Half from link.h is now called The_Elf64_Half_I_dont_care in case you ever have to use it explicitly in this file.
What do I do in such a case?
A common remedy is to put the one which needs the least visibility behind a "compilation firewall". That is, to create your own abstraction/interface which provides the functionality you need, and then to limit the visibility of the included file to the *.cpp by including it in that *.cpp only. Of course, that *.cpp file would also not be permitted to include the header which has the other definition of the typedef.
Then the declarations won't cause conflict because they will never be visible to the same translation unit.
In your example, you'd likely create a wrapper over the dlinfo() functionalities you need. To illustrate:
DLInfo.hpp
namespace MON {
class DLInfo {
public:
/* ...declare the necessary public/client functionality here... */
int foo();
...
};
}
DLInfo.cpp
#include "DLInfo.hpp"
// include the headers for dlinfo() here.
// these includes should not be in your project's headers
#include <link.h>
#include <dlfcn.h>
// and define your MON::DLInfo implementation here, with full
// ability to use dlinfo():
int MON::DLInfo::foo() {
...
}
...
Here's a little work around I figured out: If you define it as something else first, then you can typedef it later. See here in the example (I'm on OS X using g++):
#import <iostream>
using namespace std;
typedef unsigned int uint32;
int main() {
cout << sizeof(uint32) << endl;
}
The output of this program is
4
Now consider this modified program:
#import <iostream>
using namespace std;
typedef unsigned int uint32;
#define uint32 blah
typedef unsigned long uint32;
int main() {
cout << sizeof(uint32) << endl;
}
The output of this program is
8
So to answer your question, you would add a line to your code:
#define Elf64_Half Elf64_Half_custom
For clarity, this works because you are basically renaming them all, but doing so with a single command instead of having to change all of your own names.
Related
I want to run a small simulation in c++.
To keep everything nice and readable I seperate each thing (like all the sdl stuff, all the main sim stuff, ...) into it's own .h file.
I have some variables that I want all files to know, but when I #include them in more then one file other the g++ compliler sees it as a redefinition.
I understand why he does this, but this still leaves me with my wish to have one file where all important variables and constants for each run are defined and known to all other files, to easily find and change them when running my simulation.
So my Question here: Is there a good workaround to achieve that or something similar?
You can put the declarations for all the globals in a header and then define them in a source file and then you will be able to use those global variables in any other source file by just including the header as shown below:
header.h
#ifndef MYHEADER_H
#define MYHEADER_H
//declaration for all the global variables
extern int i;
extern double p;
#endif
source.cpp
#include "header.h"
//definitions for all the globals declared inside header.h
int i = 0;
double p = 34;
main.cpp
#include <iostream>
#include "header.h" //include the header to use globals
int main()
{
std::cout << i <<std::endl;//prints 0
std::cout<< p << std::endl;//prints 34
return 0;
}
Working demo
Mark them as extern in the header and have one translation unit that defines them.
Note: Without LTO (link time optimization) this will seriously slow down your simulation.
Suppose I have two data structures that reference each other. I want to put them into their separate header files like this:
// datastruct1.h
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
#include <datastruct2.h>
typedef struct DataStructOne_t
{
DataStructTwo* two;
} DataStructOne;
#endif
and
// datastruct2.h
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
#include <datastruct1.h>
typedef struct DataStructTwo_t
{
DataStructOne* one;
} DataStructTwo;
#endif
and I have a main function:
#include <datastruct1.h>
#include <datastruct2.h>
int main()
{
DataStructOne* one;
DataStructTwo* two;
}
However my compiler complains:
$ gcc -I. -c main.c
In file included from ./datastruct1.h:4,
from main.c:1:
./datastruct2.h:8:2: error: unknown type name ‘DataStructOne’
8 | DataStructOne* one;
| ^~~~~~~~~~~~~
Why is that? What can I do to fix this?
Why?
In order to understand why, we need to think like a compiler. Let's do that while analysing main.c line by line. What would a compiler do?
#include <datastruct1.h>: Put "main.c" aside (push to the stack of files being processed) and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: hmm, this is not defined, let's continue.
#define DATA_STRUCT_ONE: OK, defined!
#include <datastruct2.h>: Put "datastruct1.h" aside and switch to "datastruct2.h"
#ifndef DATA_STRUCT_TWO: hmm, this is not defined, let's continue.
#define DATA_STRUCT_TWO: OK, defined!
#include <datastruct1.h>: Put "datastruct2.h" aside and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: this is now defined, so go straigh to #endif.
(end of "datastruct1.h"): close "datastruct1.h" and pop current file from the stack of filles. What were I doing? Ahh, "datastruct2.h". Let's continue from the place where we left.
typedef struct DataStructTwo_t ok, starting a struct definition
DataStructOne* one; Wait, what is DataStructOne? We have not seen it? (looking up the list of processed lines) Nope, no DataStructOne in sight. Panic!
What happened? In order to compile "datastruct2.h", the compiler needs "datastruct1.h", but the #include guards in it "datastruct1.h" prevent its content from being actually included where it's needed.
The situation is symmetrical, so if we switch the order of #include directives in "main.c", we get the same result with the roles of the two files reversed. We cannot remove the guards either, because that would cause an infinite chain of file inclusions.
It appears that we need "datastruct2.h" to appear before "datastruct1.h" and we need "datastruct1.h" to appear before "datastruct2.h". This does not seem possible.
What?
The situation where file A #includes file B which in turn #includes file A is clearly unacceptable. We need to break the vicious cycle.
Fortunately C and C++ have forward declarations. We can use this language feature to rewrite our header files:
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
// No, do not #include <datastruct2.h>
struct DataStructTwo_t; // this is forward declaration
typedef struct DataStructOne_t
{
struct DataStructTwo_t* two;
} DataStructOne;
#endif
In this case we can rewrite "datastruct2.h" the same way, eliminating its dependency on "datastruct1.h", breaking the cycle in two places (strictly speaking, this is not needed, but less dependencies is always good). Alas. this is not always the case. Often there is only one way to introduce a forward declaration and break the cycle. For ecample, if, instead of
DataStructOne* one;
we had
DataStructOne one; // no pointer
then a forward declaration would not work in this place.
What if I cannot use a forward declaration anywhare?
Then you have a design problem. For example, if instead of both DataStructOne* one; and DataStructTwo* two; you had DataStructOne one; and DataStructTwo two;, then this data structure is not realisable in C or C++. You need to change one of the fields to be a pointer (in C++: a smart pointer), or eliminate it altogether.
One way to resolve the circular dependency and still use the typedefs where possible is to split the headers into two parts with a separate guard macro for each part. The first part provides typedefs for incomplete struct types and the second part completes the declarations of the struct types.
For example :-
datastruct1.h
#ifndef DATA_STRUCT_ONE_PRIV
#define DATA_STRUCT_ONE_PRIV
/* First part of datastruct1.h. */
typedef struct DataStructOne_t DataStructOne;
#endif
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
/* Second part of datastruct1.h */
#include <datastruct2.h>
struct DataStructOne_t
{
DataStructTwo *two;
};
#endif
datastruct2.h
#ifndef DATA_STRUCT_TWO_PRIV
#define DATA_STRUCT_TWO_PRIV
/* First part of datastruct2.h. */
typedef struct DataStructTwo_t DataStructTwo;
#endif
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
/* Second part of datastruct2.h */
#include <datastruct1.h>
struct DataStructTwo_t
{
DataStructOne *one;
};
#endif
main.c
/*
* You can reverse the order of these #includes or omit one of them
* if you want.
*/
#include <datastruct1.h>
#include <datastruct2.h>
int main(void)
{
DataStructOne *one;
DataStructTwo *two;
}
As mentioned in the comment in main.c above, only one of the headers needs to be included since the other header will be included indirectly anyway.
Well, if both structures reference each other, it is clear that they must be related. The best thing you can do is to put both in one include file (as they are related) but putting them in different and making the compiler to read from one include the other will make the compiler to read the main file... .from main file start reading include A until it gets to the point to include B, and start reading B to the point of the include A again(we'll start reading A again in a recursive manner that has no end) you will never stop reading each file and worse, you will get an error the second time you see the same struct definition (because it has been already defined before)
To allow the user to include any or both files without a problem, a define is made when include file A is encountered:
File A.h
#ifndef INCLUDE_FILE_A
#define INCLUDE_FILE_A
/* ... the whole stuff of file A with the proper includes of other files.*/
#include "B.h"
#endif /* INCLUDE_FILE_A */
and in
File B.h
#ifndef INCLUDE_FILE_B
#define INCLUDE_FILE_B
/* ... the whole stuff of file B with the proper includes of other files.*/
#include "A.h"
#endif /* INCLUDE_FILE_B */
so the definitions made in file A are only used if INCLUDE_FILE_A has not been included previously, and skip them if file A has been included already (and the same for B.h, of course).
If you make the same on file B (but instead with INCLUDE_FILE_B) then you will be secure that both files will be included in either order (depending on how you did it in the first case) and will never be included again (making th e inclussion secure of returning back to the main file.
I think I'm doing something stupid, but I don't quite know what. I'm trying to rewrite a fairly simple library I have that is reading in some variables from a text file and then shares them with some other source files for use elsewhere. When I wanted to pass a double I was doing this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include <vector>
extern double coeff_A;
#endif
and then doing this in both the source file where it was defined and the other source files where I want to use it:
#include "SharedVariables.h"
to make coeff_A available in the new source file.
But then my model got more complicated and I was using more coefficients so I decided to store them in a structure and pass that structure using extern instead. I created a new header file for the structure (CParameters.h):
#pragma once
#if !defined(CParameters_h)
#define CParameters_h
typedef struct
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
} SGlobalParameterData;
#endif
and then defined the struct like this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include "CParameters.h"
#include <vector>
extern SGlobalParameterData globalParameters;
#endif
In the first source file where I read in all the values from the data files and using the values I've replaced:
#include "SharedVariables.h"
double coeff_A;
...
with
#include "SharedVariables.h"
SGlobalParameterData globalParameters;
globalParameters = readProperties(prefsFile);
....
In the second source file which also needs to use some of these variables I've added #include "SharedVariables.h" and then the IDE and compiler let me easily access globalParameters.coeff_A, globalParameters.coeff_B, etc.
I thought this should work and everything compiles without any errors, but it's not actually passing the values read into globalParameters to the second source file. Everything is just zero when I'm debugging the code.
So there are really two questions: 1) Is it possible to share structs using extern like for double, and 2) if it is, what have I done wrong.
Hopefully someone can point out my mistake.
Edit
I've added in an line of code in my example to show the function that assigns the values to the struct. This is working and the values read from the prefsFile are available and correct in the f1rst source file, but these values are not passed to source file 2. I'm going to do some more testing because it appears I may have made some other mistake elsewhere.
Your confusion stems from the use of typedef and mixing of declarations and definitions.
In C++ typedef isn't needed to define a struct type and is only confusing.
typedef struct { ... } SGlobalParameterData; - this declares a type SGlobalParameterData that is a struct. It defines no instance of the struct.
struct SGlobalParameterData { ... }; - same thing, declares a type SGlobalParameterData that is a struct.
struct { ... } globalParameterData; - this defines an object globalParameterData of an unnamed struct type.
struct SGlobalParameterData { ... } globalParameters; - this defines an object globalParameters of an struct type called SGlobalParameterData.
So... the following might be most readable/clean IMHO:
In the header:
struct SGlobalParameterData // type declaration
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
};
extern SGlobalParameterData globalParameters; // global instance *declaration*
In one of source files:
#include "the header above"
SGlobalParameterData globalParameters; // global instance *definition*
In other source files:
#include "the header above"
// globalParameters is already visible and usable
Of course you have to compile all source files and link them together into an executable.
Is it possible to share structs using extern like for double
Yes.
if it is, what have I done wrong.
Something that you haven't shown to us.
Everything is just zero
This is to be expected because variables with static storage are zero-initialised, and you never modify globalParameters in the example.
Here is your code running. Only change I made was to add some output, and actually set some other value than zero. That non-zero value works as expected: https://wandbox.org/permlink/CasO8c68W3FmBsQH
I have the following code that throws a compile error when compiling x.cpp (conflicting declaration 'typedef struct THE_TYPE_STRUCT THE_TYPE', on last line in y.h, g++ 5.3.0):
// x.h file
struct THE_TYPE;
class C{
THE_TYPE * t;
};
// x.cpp file
#include "x.h"
extern "C"{
#include "y.h"
}
// y.h file
struct THE_TYPE_STRUCT {
int x;
};
typedef struct THE_TYPE_STRUCT THE_TYPE;
File y.h is a C header that can not be included at the beginning of the header x.h because of conflicting names with other header files, so I have to make a forward definition for THE_TYPE. Seems that it's not completely properly. How do I do it properly?
C is not the same as C++ and have different rules (for example, typedef struct THE_TYPE THE_TYPE; is useless -since implicit- in C++ but meaningful in C).
You should generate the preprocessed form (e.g. with g++ -C -E x.cpp > x.ii) then study it. A possible trick is to remove line information (starting with #) by running g++ -C -E x.cpp | grep -v '^#' > x.ii then recompile using g++ -Wall -c x.ii and look into the faulty locations in x.ii
Without knowing the actual files involved, we cannot help (e.g. perhaps some file has some #define THE_TYPE).
How do I do it properly?
In C++, you'll probably use namespace-s (notably in your own files) and avoid macros.
In C, you probably should edit your files, and I suggest to add a common prefix to every public name in your own code. You might take inspiration from GTK where every name is starting with Gtk or GTK or _GTK etc...
In general you need some consistent naming conventions and you probably need to edit all your files.
Change
struct THE_TYPE_STRUCT {
int x;
};
typedef struct THE_TYPE_STRUCT THE_TYPE;
to
typedef struct THE_TYPE_STRUCT {
int x;
}THE_TYPE;
I use the following scheme in my current project mixing a bit of c++11 code into a c11 codebase:
basedecl.h (included everywhere):
// [...]
#ifdef __cplusplus
# define pocaslibs___cdecl extern "C"
# define DECLDATA
# define C_CLASS_DECL(t) struct t
# define C_ENUM_DECL(t) enum t
#else
# define pocaslibs___cdecl
# define DECLDATA extern
# define C_CLASS_DECL(t) typedef struct t t
# define C_ENUM_DECL(t) typedef enum t t
#endif
// [...]
Forward-declaring struct types (also used for "private" types):
C_CLASS_DECL(PG_Menu);
C_CLASS_DECL(PG_Window);
Declaring "public" struct types:
C_CLASS_DECL(PG_Bounds);
struct PG_Bounds
{
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
};
Works quite nicely for both languages. The macro is named C_CLASS_DECL because in my codebase, this is really used for creating OO classes in c. If your usecase has nothing to do with OO, better think about a better name ;)
I had a .h file with some class code - overlay.h
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
Now I moved the struct to another new file called member.h
and included this file so my class overlay_server could use it.
Now when I build the program I get the error.
What changes should I make to make this work?
I read about header guards on SO, but couldnt really understand how to implement it here to solve the problem.
----edit----
member.h
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
run.cpp
#include<overlay_server.h>
#include<overlay_client.h>
int main(){
overlay_server overlay_server_(8002);
boost::thread thread_(boost::bind(&overlay_server::member_list_server, overlay_server_));
overlay_client overlay_client_("127.0.0.1",8002);
overlay_client_.member_list_client();
thread_.join();
}
I dont have redefinition of struct anywhere.
I have another class called overlay_client it also uses struct member.
In my main function, i create objects of both overlay_server and overlay_client.
Now my program runs only if member.h is included in overlay_server.h (though code in both overlay_server and overly_client requires it)
if its included in both then i get the redefinition error
why?
----edit----
this code in my member.h solves the issue
Compile error "'struct' type redefinition" although it's the first definition for it
You can also use a pragma and get the same effect. At the top of all your header files, write:
#pragma once
rest of the header
.
.
.
And the way to use include guards is to surround all the contents in a header file with an include guard, which looks like this:
// At the very top
#if !defined(SOME_SYMBOL)
#define SOME_SYMBOL
rest of the header
.
.
.
// At the very bottom
#endif // SOME_SYMBOL
Now, choosing a sensible name instead of SOME_SYMBOL is very important. Most programmers make a guard name based on the file name (and path and project name and company/individual name.) For example, for a header named "some_header.h" (or "SomeHeader.h") located in "[project root]/include/myproject", you would name the guard name to be __INCLUDE__MY_PROJECT__SOME_HEADER_H__. But this is just a suggestion; any unique symbol will do.
You can also combine the pragma and the include guards (because the pragma method can improve the compile time in very large projects, but not all compilers support it.) If you want them both, you'd write:
#pragma once
#if !defined(__INCLUDE__MY_PROJECT__SOME_HEADER_H__)
#define __INCLUDE__MY_PROJECT__SOME_HEADER_H__
rest of the header
.
.
.
#endif // __INCLUDE__MY_PROJECT__SOME_HEADER_H__
This has no adverse effects (to my knowledge,) only the potential to prevent build errors and to make your builds faster (on large projects.) But note that the meanings of include guards and #pragma once are not exactly the same. In very very rare cases, you would need to use one or the other, or neither.
This is whats happening.
you have
member.h
included in overlay_server.h and in overlay_client.h
now when you include these two in main.cpp
it is like you are doing this in main.cpp(actually preprocessor expands like below)
#include"member.h"
#include"member.h"
so it typically will be like this after complete expansion
struct member{...};
struct member{...}; //redifinition!!
so the compiler parses it as being two definition of struct member(because it will visit member.h twice and read the def of member struct).
what to do to avoid this
in member.h add this
#ifndef MEMBER_DECL //initially not defined
#define MEMBER_DECL //include guard(now first time you enter this MEMBER_DECL will get defined. so second time compiler comes here it skips this.)
struct member
{
//rest here
};
#endif
now in main you will have this
#include"member.h" //when this happens MEMBER_DECL is defined
so
//#include"member.h" member will not be expanded again hence resolving your redfinition
If overlay.h contains a struct member definition and member.h also has a struct member definition, you cant include member.h from overlay.h. Here is how include guards work though:
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
#ifndef _H__MEMBER_
#define _H__MEMBER_
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
#endif
Notice the #ifndef _H__MEMBER_ and #define _H__MEMBER_ and #endif. With the include guards, it makes sure your header is only included once because after the first time it's included H_MEMBER_ will be already defined so it will skip the definition. Your naming convention can be different but usually I do something along the lines of _H__<HEADER NAME>_ as my defines.