Really barebones implementation of one of the many ways that it is suggested
This is a simple-as-possible example of an often-recommended way of writing cross-platform C code. The example shows a solution for creating a cross-platform sleep(). Windows and POSIX systems define their sleep functions in different headers. On Windows, the function is Sleep() with a capital S, and expects the sleep duration to be in milliseconds. On POSIX, the function has a lowercase S (sleep()) and expects the sleep duration to be in seconds. The example code is so small that it looks very over-engineered, but it serves as a stand-in for how the approach would be implemented in larger projects.
There are a few benefits of this approach:
- No usage of the C preprocessor to solve the problem.
- There is no conditonal inclusion of code inside a function. The solution does not require any code that looks like this:
void my_cross_platform_function() { #ifdef _WIN32 // do dome stuff. my existence is decided by a preprocessor #endif // rest of the code }
- There is also no conditional inclusion of header files. The solution does not require any code that looks like this:
#ifdef _WIN32 #include "windows_stuff.h" #else #include "posix_stuff.h" #endif void my_cross_platform_function() { #ifdef _WIN32 my_windows_stuff_function() #else my_posix_stuff_function() endif }
- There is no conditonal inclusion of code inside a function. The solution does not require any code that looks like this:
- All platform-specific code lives its own sub-directory for that platform.
- Utilizes the build system to determine the platform (and therefore what code to build).
So what does the actual solution look like?
void my_cross_platform_function() {
platform_function();
}- All platform-specific code is in a
platforms/directory.- For small examples like this, one
.cfile and one.hfile exist for each platform (windows.c,windows.h,posix.c,posix.h). - For larger projects, a subdirectory of
platforms/for each platform would be used (i.eplatforms/windows/io.c) - This makes it clear that all other code in the project is cross-platform. All the platform-specific weirdness is contained to
platforms/.
- For small examples like this, one
- For each platform where platform-specific code is required, a
platform_myfunc()is created in each platforms source-file. - A cross-platform wrapper function is created that makes a call to
platform_myfunc(), calledmyfunc(). - At compile time, the build system determines the host platform, and include only the source files from
platforms/for the host platform.# Check if the target system is Windows. if host_machine.system() == 'windows' sources += 'src/platforms/windows.c' else
- The compiler and linker resolve
platform_myfunc(), and a cross-platform function calledmyfunc()is available that can be called.