Reputation: 28278
I am currently using the popen
function in code that is compiled by two compilers: MS Visual Studio and gcc (on linux). I might want to add gcc (on MinGW) later.
The function is called popen
for gcc, but _popen
for MSVS, so i added the following to my source code:
#ifdef _MSC_VER
#define popen _popen
#define pclose _pclose
#endif
This works, but i would like to understand whether there exists a standard solution for such problems (i recall a similar case with stricmp
/strcasecmp
). Specifically, i would like to understand the following:
_MSC_VER
the right flag to depend on? I chose it because i have the impression that linux environment is "more standard".#define
's in some header file, is it important whether i #include
it before or after stdio.h
(for the case of popen
)?_popen
is defined as a macro itself, is there a chance my #define
will fail? Should i use a "new" token like my_popen
instead, for that reason or another?Upvotes: 5
Views: 259
Reputation: 67127
Instead of ending up with cluttered files containing #ifdef
..#else
..#endif
blocks, I'd prefer a version using different files for different platforms:
#define
a macro my_popen
#include
this file in your platform-agnostic code#define
that you created (i.e. my_popen
)config/windows/mydefines.h
on windows and config/linux/mydefines.h
on linux, so set the include path appropriate and always #include "mydefines.h"
)That's a much cleaner approach than having the OS decision in the source itself.
If the methods you're calling behave different between windows and linux, decide which one shall be the behavior you're using (i.e. either always windows behavior or always linux behavior) and then create wrapper methods to achieve this. For that, you'll also need not only two mydefines.h
files but also to myfunctions.c
files that reside in the config/OSTYPE
directories.
Doing it that way, you also get advantages when it comes to diff the linux and the windows version: you could simply diff two files while doing a diff on the linux and windows blocks of the same file could be difficult.
Upvotes: 0
Reputation: 78943
The way you are doing it is fine (with the #ifdef
etc) but the macro that you test isn't. popen
is something that depends on your operating system and not your compiler.
I'd go for something like
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 2)
/* system has popen as expected */
#elif defined(YOUR_MACRO_TO DETECT_YOUR_OS)
# define popen _popen
# define pclose _pclose
#elif defined(YOUR_MACRO_TO DETECT_ANOTHER_ONE)
# define popen _pOpenOrSo
# define pclose _pclos
#else
# error "no popen, we don't know what to do"
#endif
Upvotes: 1
Reputation: 1734
Upvotes: 3
Reputation:
_MSC_VER
is the correct macro for detecting the MSVC compiler. You can use __GNUC__
for GCC.
If you are going to use popen
as your macro ID, I suggest you #include
it after, because of 3.
If you #include
it after stdio.h
, it should work AFAIK, but better safe than sorry, no? Call it portable_popen
or something.
Many projects (including some of mine) have a portability header, but it's usually better to roll your own. I'm a fan of doing things yourself if you have the time. Thus you know the details of your code (easier to debug if things go wrong), and you get code that is tailored to your needs.
Not that I know of. I do stuff like this all the time, without problems.
Upvotes: 1