Please Don't Do This
So I was working with a popular, open-source C library and came across something like this:
#if defined(!WINDOWS)
// Make things portable
#define closesocket close
// etc...
#endif
I’m not going to state which library as the details don’t really matter here.
Please don’t do this! My code was written in C++ and used another C++
cross-platform wrapper library that had its own class members named
“closesocket” and “close.” For the sake of clarity, let’s call them Lib::closesocket()
and Lib::close()
. The end result is when I included both
headers in my source files, Lib::closesocket()
got renamed to Lib::close()
and I got multiple definition compiler errors.
Look, I get that writing cross-platform code is tough. I get that you’ll want to have some sort of abstractions to mask the differences between the different platforms. But please don’t use the preprocessor to redefine symbols as you will end up breaking other code that assumes the symbols have their original names or that may have symbols with names just similar enough for the pre-processor to end up renaming them.
As for how I got around this? I ended up refactoring a bunch of code to use the PIMP idiom and put all the code using the “bad” library header in separate headers and source files away from my mainline code that caused the conflict. I may still have additional conflicts I didn’t completely resolve as of yet, but it’s working for now and I think I’ll be able to fix others as they come up.
As for as what I think is the “right” way to write cross-platform code, well it
just so happens that I worked on a library to abstract the differences between
multiple Unix versions and Windows way back when. The way we did it was we had
wrapper functions, say something like companyname_socket()
(it was a pure C
library) declared in header files and implemented in the source files with
appropriate #ifdef
s in the function bodies. As far as the extra overhead of
the extra function calls, I think the better inlining support offered by C99 and
newer compilers (we weren’t using C99 at the time I worked on that library) will
deal with the issue and result in zero or almost zero overhead in calling the
wrapper functions.