6

Vorrei scrivere una funzione multipiattaforma in C++ che contenga chiamate di sistema. Quali flag di compilazione condizionale posso controllare per determinare per quale sistema operativo viene compilato il codice? Sono interessato principalmente a Windows e Linux, utilizzando Visual Studio e GCC.Compilazione condizionale in C++ basata sul sistema operativo

penso che dovrebbe essere simile a questa:

void SomeClass::SomeFunction() 
{ 
    // Other code 

#ifdef LINUX 
    LinuxSystemCall(); 
#endif 

#ifdef WINDOWS 
    WindowsSystemCall(); 
#endif 

    // Other code 
} 

risposta

7

mio gcc (4.3.3) definisce le seguenti macro predefinite Linux-correlati:

$ gcc -dM -E - < /dev/null | grep -i linux 
#define __linux 1 
#define __linux__ 1 
#define __gnu_linux__ 1 
#define linux 1 

Sotto VC++ (e molti altri Win32 compilatori) ci sono anche un paio di macro predefinite che identificano la piattaforma, in particolare _WIN32. Ulteriori dettagli: http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx

+3

C'è un Gotcha quando si tratta di compilazione condizionale Win32/Win64 - durante la compilazione per Win64 troverete che _WIN32 è definita in modo di prova contro di _WIN64 prima prova (!) contro _WIN32 –

7

Non c'è un modo standard per farlo. Potrebbe essere possibile disattivare determinati macro definiti per piattaforma. Ad esempio, _WIN32 sarà definito su Windows e quasi certamente non su Linux. Tuttavia non conosco alcuna macro Linux corrispondente.

Poiché si utilizzano compilatori separati, ne deriva che si dispone di ambienti di compilazione separati. Perché non aggiungere la macro da soli? Sia Visual Studio che GCC supportano la definizione di macro dalla riga di comando, quindi è sufficiente definirli.

+0

Mi piacerebbe utilizzare per la maggior parte dei macro per questo, si spera che i valori predefiniti definiti dai compilatori stessi. Sembra che _WIN32 e linux siano sufficienti per i miei scopi. –

+1

Certo, ma funzionerà per BSD e altri sapori UNIX? È meglio definirlo da solo (nel makefile, nel sistema di compilazione, ecc.). Se sei infelice, almeno proteggi il tuo codice con qualcosa come #ifdef _WIN32 #define PLATFORM "Windows" #endif poi #ifndef PLATFORM #error PLATFORM indefinito - controlla la tua configurazione #endif – plinth

5

cerco sempre di mantenere le specifiche di piattaforma fuori dal codice principale da fare in questo modo

platform.h:

#if BUILD_PLATFORM == WINDOWS_BUILD 
#include "windows_platform.h" 
#elif BUILD_PLATFORM == LINUX_BUILD 
#include "linux_platform.h" 
#else 
#error UNSUPPORTED PLATFORM 
#endif 

someclass.c:

void SomeClass::SomeFunction() 
{ 
    system_related_type t; 
    // Other code 
    platform_SystemCall(&t); 
    // Other code 
} 

Ora, in windows_platform.h e linux_platform.h digitate system_related_type nel tipo nativo e sia #define platform_SystemCall come la chiamata nativa, sia create una piccola funzione di wrapper , se l'argomento impostato da una piattaforma all'altra è troppo diverso.

Se le API di sistema per una particolare attività sono molto diverse tra le piattaforme, potrebbe essere necessario creare un'API di versione che divida la differenza. Ma per la maggior parte, ci sono mappature abbastanza dirette tra le varie API su Windows e Linux.

Anziché affidarsi a qualche particolare compilatore #define per selezionare la piattaforma, #define BUILD_PLATFORM nel file di progetto o nel makefile, poiché devono comunque essere univoci per piattaforma.

0

Ecco cosa uso. Funziona in Visual Studio 2008, e MinGW:

#ifdef __GNUC__ 
    #define LINUX 
#else 
    #define WINDOWS 
#endif 

#ifdef WINDOWS 
    #include "stdafx.h" 
#else 
    #include <stdlib.h> 
    #include <string.h> 
    #include <stdio.h> 
    #include <ctype.h> 
    #include <assert.h> 
    #include <malloc.h> 
#endif 
Problemi correlati