This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
the role of #ifdef and #ifndef
Does
#ifndef _WIN32
instruct the cpp to omit the code for 32 bit windows platform ?
#ifndef _WIN32 tells the pre-processor to include the code below it till a corresponding #endif, if _WIN32 is not defined.
#ifndef _WIN32
#define STR1 "Some String"
#endif
The macro STR1 will get included if _WIN32 is not defined and will not get included if _WIN32 is defined. Please note that _WIN32 is a system defined macro. Generally, the code which is not meant for Windows platform or which is generic and cannot be compiled in Windows is placed under such #ifndef _WIN32 macros.
The MSDN page says _WIN32 will be defined by default for all 32 bit and 64 bit builds.
This directive means "don't include this code when _WIN32 macro defined".
If you define macro _WIN32 only when compile for the Win32 then this code "instruct the cpp to omit the code for 32 bit windows platform".
Well it is a preprocessor directive. It is called compilation constants.
Compiler will consider the piece of code under those #ifndef if the compilation constant(such as, _WIN32) is not defined.
I believe above explanation will help you resolving your query.
To be more specific,
#ifndef _WIN32
...
...
...
some code
...
...
...
#endif
here if you have not defined _WIN32 (such as #define _WIN32) then the code within that #if...#endif will be compiled.
hope it helps.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to interface PDFium with Cython and ran into these defines/signatures:
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __declspec(dllexport)
#else
#define FPDF_EXPORT __declspec(dllimport)
#endif // defined(FPDF_IMPLEMENTATION)
#else
#if defined(FPDF_IMPLEMENTATION)
#define FPDF_EXPORT __attribute__((visibility("default")))
#else
#define FPDF_EXPORT
#endif // defined(FPDF_IMPLEMENTATION)
#endif // defined(WIN32)
#else
#define FPDF_EXPORT
#endif // defined(COMPONENT_BUILD)
#if defined(WIN32) && defined(FPDFSDK_EXPORTS)
#define FPDF_CALLCONV __stdcall
#else
#define FPDF_CALLCONV
#endif
FPDF_EXPORT void FPDF_CALLCONV
FPDF_InitLibraryWithConfig(const FPDF_LIBRARY_CONFIG* config);
I'm just used to the simple function declaration with
return_type function_name();
How to wrap signatures containing calling conventions in Cython?
Unfortunately, I could not find the specific macros or the function you reference here: https://github.com/PDFium/PDFium
You should probably add what specific version of your library you are using.
However, there are things in C function declarations besides return type, function name, and parameters that come from outside C it self.
One specific one, which is not part of the C standard, is the calling convention, which specifies how sending parameters and returning from function works.
Since the keywords to specify this convention are compiler specific, it makes sense to put them in a conditional macro, to make the code portable.
It may also be done to support cross-compilation for different hardware.
So FPDF_CALLCONV is most likely something like this:
#ifdef SOME_CONDITION_TO_USE_STD_CALL
#define FPDF_CALLCONV __stdcall
#endif
Another non standard option in C (and C++) programs is a directive to export a function when building a DLL on Windows.
Since this is platform specific, to make C code cross-platform, it also needs to be in a conditional macro.
So, FPDF_EXPORT is likely something like this:
#ifdef WINDOWS
#define FPDF_EXPORT __declspec(dllexport)
#else
#define FPDF_EXPORT
#endif
Note, that on other platforms this kind of "marking" does not exist, so the macro can expand to nothing, leaving the function declaration in a more familiar form.
It should also be left blank in the version of h file you include to use the library as opposed to the one used to compile the library, as you don't need this prefix to call the function.
To conclude, it is likely you can omit these two macros in your Cuthon interface, assuming the library you are using is compatible with your platform.
FPDF_EXPORT and FPDF_CALLCONV are Macros, they are defined in the file :
https://pdfium.googlesource.com/pdfium/+/master/public/fpdfview.h
They are needed here because the library is available for different systems, and different systems have different conventions for creating the library interface.
These calls are extensions to the format you are familiar with:
return_type function_name(args)
For example you can see that FPDF_CALLCONV dissapears unless you are building the library for windows.
I would like to use
#include <time.h>
clock_gettime(CLOCK_TAI, &...);
but unfortunately CLOCK_TAI is not defined in stock time.h header (in openSUSE 13.2 at least). It is however defined in linux/time.h and actually supported by the operating system. But if I include the latter header, it provokes a bunch of declaration conflicts — versus both time.h and bits/types.h. Including only the linux/time.h does not help, as time.h and/or bits/types.h will be implicitly included by common headers, like unistd.h or stdlib.h, anyway.
So I tried to resolve conflicts manually. Particularly, the first compiler error message was about timespec redeclaration, so I wrote in my code:
#include <time.h>
#if defined(__timespec_defined) && !defined(_STRUCT_TIMESPEC)
#define _STRUCT_TIMESPEC
#endif
#include <linux/time.h>
It worked, but not without yet another conflict with itimerspec redeclaration, which is declared unconditionally in both headers and is not concluded with definitions of any include guards. So I decided to ban implicit time.h inclusion altogether:
#include <linux/time.h>
#ifndef _TIME_H
#define _TIME_H
#endif
This continued with compiler complaining about timeval redeclaration. So I banned implicit bits/types.h inclusion as well:
#include <linux/time.h>
#ifndef _TIME_H
#define _TIME_H
#endif
#ifndef _BITS_TYPES_H
#define _BITS_TYPES_H
#endif
Alright, but this removes important basic declarations as well, upon which common types like size_t are based. So I tried to go in the opposite direction and disable linux/types.h inclusion:
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
#endif
#include <linux/time.h>
#ifndef _TIME_H
#define _TIME_H
#endif
As you can guess, it resulted in system-specific types like __kernel_time_t being missing, which leaded to inability to declare timespec and so on.
Thus I am wondering: is it at all possible to use linux/… headers in combination with stdlib.h and other commonly included files? Are there other ways to access system-specific CLOCK_TAI value?
First I have to explain my ...
Situation
I have this microcontroller code (plain old C) which includes bool.h with the following content since stdbool.h is apparently not available, especially not with Visual Studio 2008, which is my current IDE for VC++ and C# (see below):
#ifndef CUSTOM_BOOL
#define CUSTOM_BOOL
#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus
#ifndef bool
#define bool unsigned char
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
#endif // #ifndef CUSTOM_BOOL
Now I need the functionality of that microcontroller code in a C# Project. That's why I created an intermediate Visual C++ Project containing managed classes that wrap the given microcontroller code.
Since this wrapper project (VC++) fiddles about the C code, it also has to #include "bool.h" (in an indirect way however, which means that another header is included, which itself includes bool.h - but I think that's an unimportant detail). Now here's my ...
Problem
Due to the fact that bool.h is included in the VC++ project and this project shall provide functions that return a "real" bool ("real" here means a type that is recognized as a bool by C# when using the VC++ project), unfortunately the bool in the VC++ code is also caught by the preprocessor and thus replaced by unsigned char. What happens now is, that C# complains in the end that a conversion from unsigned char to bool is not allowed. This is all okay and I understand why this happens. So here's my ...
Question
How can I solve this issue in a "clean" way. My current solution is, after including bool.h and right before the VC++ code starts, I undefine bool and friends again like this:
#ifdef bool
#undef bool
#endif
#ifdef true
#undef true
#endif
#ifdef false
#undef false
#endif
It works, but it breaks my proper-way-of-programming-heart. Is there a proper way to fix this? Or is the problem maybe happening before? Should I instead define something like BOOL instead of bool? According to my search on the interwebz, there is no general "standard" way to define bool (or BOOL?) in a C project (C99 is not supported) that everybody would agree upon.
So it sounds like the microcontroller project just made up a new data type and called it bool, which happens to conflict now that bool is a keyword (along with true and false)? My suggestions (in order of preference) would be:
Solution 1: Fix the microcontroller project.
Do a global search and replace on bool and replace it with something less contentious. Maybe C_Boolean, C_True, and C_False. Unlikely to cause any future conflicts and fairly simple to do using regular expressions.
Solution 2: Convert microcontroller project to C++.
This allows direct use of bool, true, and false (as keywords) and you can just eliminate the macros. This may prove difficult if the microcontroller code uses syntax that isn't c++ compatible.
Solution 3: Do what you've already done.
Create a wrapper include which cleans up after including your microcontroller code. I've got code that relies on redefining the extern keyword and this ends up being the only safe way for me. It's fragile though...you'll likely have to fix it in the future when something unrelated breaks the include structure.
Also, I'm not sure what the original author believes the extern "C" wrappers are doing but they have no effect on the macros being defined. Maybe you cut out some stuff that it would have an effect on, but the macros are unaffected by the linker name conventions.
You could convert the return value (the char) to a boolean value by using an operator. In this case, for instance, you could simply compare the return value this way:
bool b = 0 != functionthatreturnsaboolean();
Note that I'm not using 1 since the usualt definition of a boolean is 0 for false, anything else otherwise.
The other solution would be to simply use another type of return value. An integer should work well.
Edit: In light of the comment - you could also simply create an interface that calls those functions and returns a C# boolean value.
bool interfacefunction()
{
return function() != 0;
}
Thanks to Keith Thompson (comment under the question) and Speed8ump's answer, I got another idea:
bool.h:
#ifndef CUSTOM_BOOL
#define CUSTOM_BOOL
#ifndef __cplusplus
#ifndef bool
#define bool unsigned char
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#endif // #ifndef __cplusplus
#endif // #ifndef CUSTOM_BOOL
Works like a charm and I think it's a cleaner solution than the undefining stuff before. But still, feel free to comment or to provide more / better answers.
We use #warning to show compile message, like this:
#warning Are you sure it is correct?
Is is possible redefine the #warning and can choice if enable or disable it, like this:
#ifdef ACTIVE_MY_WARNING
#define #my_warning #warning
#else
#define #my_warning
#endif
We can do it in C or not?
No, it's not possible to redefine preprocessor keywords (#if, #define, #ifdef, etc).
Your best shot is to have a parser that can replace your code with:
#ifdef ACTIVE_MY_WARNING
#warning Are you sure it is correct?
#endif
You tag it in C
and as per my knowledge there is no
preprocessor live #warning in c.
My question for you ans " We can do it in C or not? "
is No.
I'm using two computers, each with a different version of visual studio. On the visual studio 2008 computer my code compiles. On the visual 2010 computer my code doesn't compile because I'm using the macro max(a,b) which as far as I know is defined in stdlib.h. I cannot just define max(a,b) because it'll be a redefinition on the visual 2008 computer. But if I don't define max(a,b) my code doesn't compile on the visual 2010 computer.
Any solution?
Any C library which defines a macro named max in its standard headers is broken beyond imagination. Fortunately, an easy workaround if you need to support such platforms is to #undef max (and any other problematic macros it defines) after including the system headers and before any of your own headers/code.
Note that everyone else is saying to wrap your definition in #ifndef max ... #endif. This is not a good idea. Defining max in a system header is an indication that the implementor was incompetent, and it's possible that certain versions of the environment have incorrect macros (for example, ones which do not properly protect arguments with parentheses, but I've even seen a max macro that was incorrectly performing min instead of max at least once in my life!). Just use #undef and be safe.
As for why it's so broken for stdlib.h to define max, the C standard is very specific about what names are reserved for the application and what names are reserved for standard functions and/or internal use by the implementation. There are very good reasons for this. Defining macro names in system headers that could clash with variable/function names used in the application program is dangerous. In the best case it leads to compile-time errors with an obvious cause, but in other cases it can cause very strange behavior that's hard to debug. In any case it makes it very difficult to write portable code because you never know what names will already be taken by the library.
So answering your main question:
Is max(a,b) defined in stdlib.h or not?
No it isn't, it's defined in windef.h around line 187:
#ifndef NOMINMAX
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#endif /* NOMINMAX */
Protect it with an #ifndef.
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
Keep in mind that the version above is not as safe as an inline function, e.g. max(a++,b--) will cause unxpected results.
you can use condition compiling:
#ifndef max
#define max(a,b) ...
#endif
In Visual C++, if you #define NOMINMAX before including the standard headers, you will not get a macro max or min.