using #if to run a function - c++

I'm trying to run the expression _setmode only if I'm using Windows, and setlocale only if I'm using Linux, but I can't manage to make them work with a simple if-else inside a function due to Linux having errors with the Windows libraries, and vice versa.
#if defined(_WIN32) || defined(_WIN64) || (defined(__CYGWIN__) && !defined(_WIN32))
#define PLATFORM_NAME 0
#include <io.h>
#include <fcntl.h>
#elif defined(__linux__)
#define PLATFORM_NAME 1
#include <locale>
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_OS_MAC == 1
#define PLATFORM_NAME 2
#endif
#else
#define PLATFORM_NAME NULL
#endif
#if PLATFORM_NAME == 0
_setmode(_fileno(stdout), _O_U8TEXT);
#endif
#if PLATFORM_NAME == 1
setlocale(LC_CTYPE, "");
#endif

If you write OS-dependent* code (as in this case), you can manage it at compile-time**. To do this, we need two parts:
Define OS-dependent constants (optional, if condition simple, this part can be omitted):
#if defined(_WIN32)
#define PLATFORM_NAME 0
#include <fcntl.h>
#include <io.h>
#elif defined(__linux__)
#define PLATFORM_NAME 1
#include <locale>
#endif
In needed place call OS-dependent code with preprocessor conditions:
#if PLATFORM_NAME == 0
//Windows code here
#endif
You can write more complex conditions:
#if PLATFORM_NAME == 0
//Windows code here
#elif PLATFORM_NAME != 0
//Non-Windows code here
#if PLATFORM_NAME == 1 || PLATFORM_NAME == 2
//Linux or unknown OS code here
#endif
#endif
See restrictions of conditions here
Tip: If your code have entrypoint (main function as example), you can call most of OS-dependent code at main if this help to reduce code. In library you can place OS-dependent code to dedicated source-file functions like there. Usage preprocessor-time code is good method for writing zero-cost runtime code because of preprocessor just remove all sources,if they're not met conditions.
* - or whatever-dependent 😃
** - more precisely, preprocessor-time
Source: GNU, Microsoft docs.

Related

count #define or const variables at compile time

In C++, I have some #define and also a count like this:
#define USE_1
#undef USE_2
#define USE_3
const size_t NUM_USE = (
0
#ifdef USE_1
+ 1
#endif
#ifdef USE_2
+ 1
#endif
#ifdef USE_3
+ 1
#endif
);
Now, I want to use it like this, which does not work as const variable cannot be used in a #if preprocessor statement:
#if NUM_USE > 0
// define here some specific code
#endif
One way to solve it would be to make some extra defines like this:
#ifdef USE_1
#define HAVE_ANY_USE
#else
#ifdef USE_2
#define HAVE_ANY_USE
#else
#ifdef USE_3
#define HAVE_ANY_USE
#endif
#endif
#endif
#ifdef HAVE_ANY_USE
// define here some specific code
#endif
Is there a more elegant solution, maybe by using NUM_USE from above?
You can define the USEs to be either 1 or 0 and then the sum can be a simple macro:
#define USE_1 1
#define USE_2 0
#define USE_3 1
#define NUM_USE (USE_1 + USE_2 + USE_3)

C++ Platform Support

I am planning to make my C++ application compatible with Windows/Mac/Linux. At the moment I came up with this "code":
#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__) || defined(__NT__)
#include <Windows.h>
#elif defined(__APPLE__) || defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#error "IOS simulator is not supported!"
#elif TARGET_OS_IPHONE == 1
#error "IOS is not supported!"
#elif TARGET_OS_MAC == 1
//MAC??????
#else
#error "Unknown Apple platform!"
#endif
#else
#error "The platform you are currently using is not compatible!"
#endif
I don't know if I implemented Windows correctly, but at least I know what to include. So my questions are:
What do I need to import to use the Mac system library?
How can I implement linux support and what do i need to include to use his library?
I need the system libraries because later I planned to make a window class based on the system's libraries, I think you can do it for Windows but I am not really if you can do it sure on linux/mac.
Update #1:
Ok so I figured out which macros to use but what libraries should I include?
#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
#define PLATFORM_WINDOWS
#include <Windows.h>
#elif defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR == 1
#define PLATFORM_IPHONE_SIMULATOR
#error "Iphone simulator environment is not compatible!"
#elif TARGET_OS_IPHONE == 1
#define PLATFORM_IPHONE
#error "Iphone environment is not compatible!"
#elif TARGET_OS_MAC == 1
#define PLATFORM_MACOS
//what do I need to include here???
#endif
#elif defined(__ANDROID__)
#define PLATFORM_ANDROID
#error "Android environment is not compatible!"
#elif defined(__linux__) || defined(__linux) || defined(linux)
#define PLATFORM_LINUX
//what do i need to include here???
#else
#error "The platform you are currently using is not compatible!"
#endif

Chromium `debugger` equivalent, on `gdb` for Cygwin?

How do people trigger a breakpoint on gdb (for Cygwin, specifically) from the very source code?
Like when a JS script has the debugger word in it and Chromium dev tools trigger stop for debugging?
Here's how SDL2 implements this feature:
#if defined(_MSC_VER)
/* Don't include intrin.h here because it contains C++ code */
extern void __cdecl __debugbreak(void);
#define SDL_TriggerBreakpoint() __debugbreak()
#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
#define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
#elif defined(__386__) && defined(__WATCOMC__)
#define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
#include <signal.h>
#define SDL_TriggerBreakpoint() raise(SIGTRAP)
#else
/* How do we trigger breakpoints on this platform? */
#define SDL_TriggerBreakpoint()
#endif
The conditionals should probably resolve to __asm__ __volatile__ ( "int $3\n\t" ) on Cygwin.

Arduino platform compiler flag

Is there's any compiler flag to indicate the platform?
e.g:
#ifdef ARDUINO_UNO
....//code for uno
#elif ARDUINO_NANO
...//code for nano
#else
error("unknown platform");
#endif
In Arduino.h file, you can find the following preprocessor checks:
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
...
#else
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
...
#endif
I never tried these, but do not I see why you will not be able to use them in your code as well.

elsif directive in c++ with 3 options

I would like to be able to switch my feed between an image, a video and a webcam.
Atm i try this:
#define F_WEBCAM
#define F_VIDEO
#define F_IMAGE
#define FEED(F_WEBCAM)
Somewhere else:
#if defined(FEED) && FEED == F_WEBCAM
ofVideoGrabber vidGrabber;
#elif defined(FEED) && FEED == F_VIDEO
ofVideoPlayer vidPlayer;
#elif defined(FEED) && FEED == F_IMAGE
// code for image
#endif
But i get the following error:
Expected value in expression
Is this possible the way i want?
To compare, you need to define your macro constants with values. This will solve your issue:
#define F_WEBCAM 1
#define F_VIDEO 2
#define F_IMAGE 3
#define FEED F_WEBCAM