coming from python and am a bit tripped up on what the proper approach to this is.
I am trying to include this library in my project:
https://github.com/nothings/stb/blob/master/stb_image.h
to do so, i have to #define STB_IMAGE_IMPLEMENTATION exactly once before importing the file (as per that file's doc)
This makes sense, where I am confused is, I have CLASS.h/cpp and in .h I define functions that use typedefs from that file, so I have
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
in that header file, and can't move these lines to .cpp as headers needs the defs for function def, but as soon as another file includes this header, (#ifndef wont help, i believe), that will be defined twice
I have a structure where TOP creates the CLASS above, but parent also creates OTHER, and OTHER needs to include PARENT, which includes CLASS, which triggers the issue (and prevents me from just moving the #define to PARENT) Note the actual class structure is more complex then this, but this idea seems to be a core issue, and I'm looking for the general best practice.
So, is there some way to ensure these #defines are defined before anything else, and done only once? This seems like a fundamental thing but I can't figure it out - What's the best approach?
This code is a library, and doesn't have a defined entry if that matters
Create a cpp file (or whatever extension you are using for your source files) whose sole purpose is to have
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
and don't forget to include this cpp file into your project so that it is compiled and the result is linked into your program. In all other places where you need something from this library, just include the stb_image.h header as usual.
These "implementation" macros are a "trick" used by some library authors to make "installing" their library easy. The idea is that when a specific macro (chosen by the library authors) is defined before the header of that library is included, some code with the actual implementation will be added. That is why this must be in a source file instead of a header and only in one source file (otherwise you get multiple definitions for the same functions).
You should have the #define STB_IMAGE_IMPLEMENTATION macro definition in exactly one source file that includes <stb_image.h> (a .cpp file, not in a header).
Since you can also only have one source file that defines main(), it is simple to put the #define in the same file as main() (as long as it also includes <stb_image.h>), but it can be used in any other source file if you prefer. You could even create a source file stb_image_imp.cpp that contains just the two lines shown, and link that into your program (or library) too.
All other source files in the project should only include <stb_image.h> without also defining the macro.
#define is a preprocessor directive and doesn't actually get run everytime the header is accessed so you should
't have any problems
if you are using visual studio you can also do #pragma once to only parse the file once stopping anything from happening twice
Related
In DirectX Graphics Samples MiniEngine sample, there is an "inline" source file Functions.inl that uses a macro INLINE that is defined in a header in same folder, Common.h .
What mechanism/declaration permits Functions.inl to use INLINE without an #include "Common.h" statement?
My specific issue is that I have created a VS2019 UWP C++ project, and I am importing a subset of this source and cannot compile the copy of Functions.inl without modifying and adding an #include statement.
"Math/Functions.inl" is not a source file. It is not compiled individually. It appears to be included, just like a header is. Let's take a look at how it is used:
// Core/VectorMath.h
#pragma once
#include "Math/Scalar.h"
...
#include "Math/Functions.inl"
Unlike a header, it is not included into the top of the file, but the bottom. So, I guess it could be called a footer. As you may notice, there are headers included before it. Let's take a look inside one:
// Math/Scalar.h
#pragma once
#include "Common.h"
...
Ah. So, "Common.h" is included before "Math/Functions.inl". That is why "Math/Functions.inl" can use INLINE when included into "Core/VectorMath.h".
Essentially, the file depends on a macro without including it directly and thereby it has an invisible dependency to have that header included before it.
This a bad practice in case of header files which are intended to be included by the user of the library. But this file is presumably intended to not be included except through "Core/VectorMath.h", so the the invisible dependency can even be seen as advantageous. Nevertheless, many IDEs / static code analysers will fail to analyse the file correctly, so I would personally still avoid this practice.
The *.inl extension is usually used to indicate that the file is an inline-definition of something defined in a header. Effectively, the *.inl file is generally treated as an inline-equivalent to a *.cpp file.
In the same way that *.cpp files can use symbols #included in the header for that *.cpp file, *.inl files usually have the same assumption.
In this specific example. it appears that Functions.inl is included after a bunch of other headers are included
#include "Math/Scalar.h"
#include "Math/Vector.h"
#include "Math/Quaternion.h"
#include "Math/Matrix3.h"
#include "Math/Transform.h"
#include "Math/Matrix4.h"
#include "Math/Functions.inl"
Which likely transitively pick up the INLINE macro
So I'm currently working on something that uses OpenCL. The OpenCL spec provides the users with a directive which must be included before the inclusion of the header (cl.h)
#define CL_TARGET_OPENCL_VERSION 110
Which basically defines the version they want to use. Suppose I'm making a library and I want my users to define this instead of me defining this inside my files. What I did was.
-----main.cpp---
#define CL_TARGET_OPENCL_VERSION 110
#include "library.h"
-------x---------
----library.h-----
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
And the compiler prints both def and ndef messages. And the OpenCL library also throws a warning that it's undefined. I thought that the library header would get substituted into main and it'd only print the def message. Is there anything I understood wrong?
I'm particularly confused as to where does the preprocessor start? If it starts from main.cpp and goes from top to down, then it surely has defined the macro. After that it sees the library inclusion, then it should only print the def message but it prints both.
This leds me to believe the preprocessor does scan the header file before including it in main? Dunno the reason why. Also I have assured that the library header isn't included elsewhere.
One interesting thing I noticed was, if i did this
-----helper.h---
#define CL_TARGET_OPENCL_VERSION 110
-------x---------
----library.h-----
#include helper.h
#ifdef CL_TARGET_OPENCL_VERSION
#pragma message("def")
#endif
#ifndef CL_TARGET_OPENCL_VERSION
#pragma message("ndef")
#endif
.... include other headers.
--------x---------
It prints the def message "twice". If anybody can explain all this I'd be grateful.
EDIT:- The files I'm compiling are main.cpp library.h and library.cpp
Library.cpp includes library.h from the start as usual. Maybe this other cpp is causing the problem?
In C/C++ programs, the compiler handles each .c and .cpp file separately.
The compilers build each source file (NOT the header files, only .c and .cpp files) independently from each other (this source files are called compilation unit).
Thus, when your main.cpp is built, the compiler finds the #define CL_TARGET_OPENCL_VERSION 110 you have added on top of the main.cpp file, emiting the defmessage.
But when the compiler builds the library.cpp file, it does not find the version define, so it emits the ndef message.
So, following this explanation, it is completely normal that in your last case, when you add the define to the .h file, the compiler emits the def message twice, once for the main.cpp file and once for the library.cpp file.
Now, the problem is where should you add the define, in order to have the program built consistently, with the same version for all the .cpp files.
Usually, all the IDEs have some configuration page where you can add global defines, for all the project, which are "inserted" into all the compilation units before everything else. So when the IDE calls the compiler, it passes the same defines to all the compilation units. You should add this kind of defines in this page.
In your IDE (I am using Code::Blocks, v 17.12), you can find this page in the menu: Project / Build Options
For each type (Debug or Release), you have to go to the tab Compiler Settings, and there to the sub tab #defines. There you can add global defines, which can be different if you are building in Debug or in Release mode (of course, if you set the same in both modes, they would be the same).
Once you have added your define here, please, remove it from the main.cpp, library.h and any other place where you may have added it, in order to avoid duplicities.
From the comments about portability:
You have several options:
Always use Code::Blocks: this would be the easiest way, since you can pass the Code::Blocks project along with the source files, and everything would be already setup.
Use cmake, which is a script build system, where you can set defines and so in the same way as using an IDE. cmake is much widely used than Code::Blocks, so maybe it is a better option.
Add a new options.h header file, where you set all the defines, and include it to all your .c/.cpp. This setup has the additional benefit that for different systems, changing only the options.h file the build can be completely different. This is a manually setup of what the IDE is doing. It has the advantage that does not rely on external tools, but the disadvantage that you have to remember to add it in all the new .cpp files added to the project.
My recommendation is go with cmake, just as the others have said.
Prefer using #ifndef XXXX_h #define XXXX_h #endif over #pragma once
If your #include search path is sufficiently complicated, the compiler may be unable to tell the difference between two headers with the same basename (e.g. a/foo.h and b/foo.h), so a #pragma once in one of them will suppress both. It may also be unable to tell that two different relative includes (e.g. #include "foo.h" and #include "../a/foo.h" refer to the same file, so #pragma once will fail to suppress a redundant include when it should have.
This also affects the compiler's ability to avoid rereading files with #ifndef guards, but that is just an optimization. With #ifndef guards, the compiler can safely read any file it isn't sure it has seen already; if it's wrong, it just has to do some extra work. As long as no two headers define the same guard macro, the code will compile as expected. And if two headers do define the same guard macro, the programmer can go in and change one of them.
#pragma once has no such safety net -- if the compiler is wrong about the identity of a header file, either way, the program will fail to compile. If you hit this bug, your only options are to stop using #pragma once, or to rename one of the headers. The names of headers are part of your API contract, so renaming is probably not an option.
(The short version of why this is problematic to use #pragma is that neither the Unix nor the Windows filesystem API offer any mechanism that guarantees to tell you whether two absolute pathnames refer to the same file.)
in my current project I´m working with the arpackpp interface. The entire library is written in .h files, so that there is no need to compile the library. The problem I'm facing now - when I include some of the arpackpp header files in some of my files, which are not the main.cpp, I get the following errors:
/.../Files/Includes/../../../arpack++/include/arerror.h:163: multiple definition of ArpackError::Set(ArpackError::ErrorCode, std::string const&)'
/.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here
/tmp/ccruWhMn.o: In functionstd::iterator_traits::iterator_category std::__iterator_category(char* const&)':
/.../Files/Includes/../../../arpack++/include/arerror.h:163: multiple definition of ArpackError::code'
/.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here
/tmp/ccruWhMn.o: In functionstd::vector >::max_size() const':
for several arpackpp functions when linking all the .o files. As I have read in several threads the problem is that I actually include the instantiation of the functions, which should be normally avoided.
Because I don't want to change the whole library I included all classes and functions using arpackpp classes in main.cpp, which is getting quite messy. Is there a workaround to this problem? And why doesn't include guards (#ifndef...#endif) prevent this problem?
First of all, include guards do not help at this point as they only prevent multiple inclusions of a header in a "subtree" of your project files' dependency graph. In other words: If you include a header in two totally separated files of the same project, the c++ preprocessor will replace the #include <header.h> twice and independently by the code specified in the header. This is perfectly fine as long as the header only contains declarations.
In your case (and in the case of many other header-only libraries), definitions are provided in the headers as well. So unfortunately (as far as I know), there is no elegant way other than including definition-containing files once in your project. https://github.com/m-reuter/arpackpp/blob/master/include/README explicitly states which files contain definitions.
Some libraries, however, provide preprocessor macros to trigger the inclusion of definitions for the provided header files (e.g. https://github.com/nothings/stb). Maybe arpackpp provides similar mechanisms.
In general the easiest way to the work with header only libraries is to extend your code only using headers. Provided you use the correct header guards, this would remove the issue of multiple definitions of your code. If you have a large base of existing code then I would suggest that you rename all your *.cpp files to *.hpp (c++ header files) and then add suitable header guards. Furthermore a convenient way of handling this code of base is to create an additional header file config.hpp and include all your other headers in that file. Then in your main.c it is a simple matter of including the config.hpp file.
e.g.
// Config.hpp ------------------------------------------------=
#include "example.hpp"
#include "example1.hpp"
#include "example2.hpp"
// etc.
// main.cpp --------------------------------------------------=
#include "Config.hpp"
int main() {
// Your code here.
return 0;
}
Furthermore if you wanted to continue with your project structure it would be a simple matter of separating all your code into functions that needed to access arpackcpp directly. Then include them all into one *.cpp file, and compile into a *.o and link.
I want to refer some stable library code which is not maintained by me. Actually it is some MFC code snippet.
But, whenever I want to include the code snippet, I have to #include entire file, which consequently I have to include other stuff, then the whole MFC ... The consequence is not acceptable.
Currently, I copy/paste the code snippet into my project, but I feel disgraceful. Can I just refer part of a file by C++ preprocessor?
Even the code is hard-linked with specific MFC version, it is better than duplicate them in my project. With such hard-link, I will know it's from MFC and save my time to check them.
Is there some super #include usage?
Can we write something like
#include "foo.h" line [12, 55)
which means to include line 22 to 54 for foo.h
What some have done is write #ifdef-sections in their headers to allow including files to only get specific parts. I don't know if your MFC file has those but you can look through it and use any existing ones or write your own.
The header usually look something like this
#ifdef USE_FANCYPANTS
bool hasFancyPants();
#endif
#ifdef USE_COOLSTUFF
void doCoolStuff();
#endif
And your include files then use #define before including.
#define USE_FANCYPANTS
#include "header.hpp"
Then you only get hasFancyPants() and not doCoolStuff()
You can use conditional compilation to inlcude/exclude stuff you dont need. You have to change the source code slighty, and amend project settings.
Can use typedef keyword, which would define types differently for MFC and non-MFC, and/or specific to your project settings, and the legacy code.
You may put entire stuff in a DLL or a .LIB (having code, not just declaration), and put the linker pragma in header file itself.
I have "Hello World" code that uses function fhi from another hi.cpp file that has it's header.
Correct my if my understanding is wrong according following:
I can do include cpp file like #include "c:\c\hi.cpp" instead of using header without any problems except that fact that it looks more readable in header file.
If I include header like sample in my main program hi.h, must hi.h include hi.cpp, or it is done automatically according the same file name hi. I'm wondering how compiler knows where is function fhi body.
Is it possible to have different names for header and cpp files?
Programm:
#include "stdafx.h"
#include "c:\c\hi.h"
int _tmain(int argc, _TCHAR* argv[])
{
fhi(1);
return 0;
}
hi.h
#include <cstdlib>
#include <iostream>
int var;
int fhi(int f);
hi.cpp
#include <cstdlib>
#include <iostream>
int fhi(int f)
{
return 0;
}
must hi.h include hi.cpp
No. hi.h contains only declarations, that can be other by other .cpp files.
I'm wondering how compiler knows where is function fhi body.
It doesn't. You need to compile all *.cpp files into the object files. In your case, you will have two object files: program.o and hi.o. The linker can now take these two object files, and spit out the executable. References to other functions(in this case the actual definition of fhi(..)) is resolved in this stage.
Also why are you using absolute paths in #includes? It will break when you move the "c" directory around.
What normally happens is that the build system compiles the .cpp files into object files, that then are used to build the main executable. The means to tell this to the build system vary greatly.
One important point is that your hi.cpp must include hi.h. You should also put an include guard in hi.h, to make it safe to be included more than once in a translation unit.
I can do include cpp file like #include "c:\c\hi.cpp" instead of using
header without any problems except that fact that it looks more
readable in header file.
yes, you can do so but it is not recommended, one of the problems is encapsulation; you are not hiding implementation details. readability as you mention is also a concern, a header is easier to read since it clearly shows what methods are public.
If I include header like sample in my main program hi.h, must hi.h
include hi.cpp, or it is done automatically according the same file
name hi. I'm wondering how compiler knows where is function fhi body.
the header needs to be explicitly included in hi.cpp and any .cpp file that use the class defined in the header.
Is it possible to have different names for header and cpp files?
yes but it is not recommended, it makes it more difficult to find things.
as a general rule: think about that other programmers may want to look in your code so you need to structure it so that it is easy to read and understand as well as making it easier for you 2 years down the road to remember where things are.
In Visual Studio all CPP files included in the project will be compiled to produce OBJ files. These OBJ files will be linked together to form the EXE or DLL.
Including files are similar to pasting the contents of the file at that location. The only difference is that this pasting is done by the pre-compiler during compilation.
Finding out where a function body resides is done by the either the compiler if the function is inline or by the linker when the final binary is created.
First, if the header file is in the same directory as the source file including it, you can use just
#include "hi.h"
In other words, you don't have to use a full path. (See e.g. the inclusion of "stdafx.h".)
Second, in your header file you don't need to include other header files, unless you need types from those. In your header file you don't have anything that needed from the header files you include.
Third, you should protect header files header files from being included more than once in the same source file, this can be done with a so called include guard, on in some compiler via a special directive called #pragma once.
Fourth, in your header file you define a global variable var. This variable will then be defined in every source file you include the header file in, which will lead to errors. You need to declare the variable as extern:
extern int var;
Then in one source file you define the variable like you do now.
Fifth, you should never include source files in header file (with some special exceptions that you don't have to think about yet). Instead you add all source files to the project (I assume you are in MS VisualStudio) and it they will all be built and linked together automatically.
Sixth, since you seem to be using VisualC++, then you are probably using something called precompiled headers. This is something the compiler uses to speed up compilation. However, for this to work you have to include "stdafx.h" in all source files. That include actually has to be the first non-comment line in each source file.