2011-12-29 23 views
33

Sto scrivendo un programma multipiattaforma. Voglio che questo programma sia eseguito sia con Windows che con Linux, quindi ho due segmenti di codice diversi per le due piattaforme. Se il sistema operativo è Windows, voglio che venga eseguito il primo segmento di codice; se è Linux, allora voglio che venga eseguito il secondo segmento di codice.Rileva Windows o Linux in C, C++

Così ho scritto il seguente codice, ma si verifica un errore durante la creazione sia su Windows che su Linux. Cosa dovrei fare per risolverlo?

#ifdef __unix__     /* __unix__ is usually defined by compilers targeting Unix systems */ 

    #define OS_Windows 0 
    #include <unistd.h> 
    #include <stdlib.h> 
    #include <stdio.h> 
    #include <string.h> 

#elif defined(_WIN32) || defined(WIN32)  /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */ 

    #define OS_Windows 1 
    #include <windows.h> 
    #include <stdio.h> 
    #include <tchar.h> 
    #define DIV 1048576 
    #define WIDTH 7 

#endif 

int main(int argc, char *argv[]) 
{ 
    if(OS_Windows) 
    { 
     MEMORYSTATUSEX statex; 
     statex.dwLength = sizeof (statex); 
     GlobalMemoryStatusEx (&statex); 

     _tprintf (TEXT("There is %*ld %% of memory in use.\n"), 
        WIDTH, statex.dwMemoryLoad); 

    } 

    else if(!OS_Windows) // if OS is unix 

    { 
     char cmd[30]; 
     int flag = 0; 
     FILE *fp; 
     char line[130]; 
     int memTotal, memFree, memUsed; 

     flag=0; 
     memcpy (cmd,"\0",30); 
     sprintf(cmd,"free -t -m|grep Total"); 
     fp = popen(cmd, "r"); 
     while (fgets(line, sizeof line, fp)) 
     { 
      flag++; 
      sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree); 
     } 
     pclose(fp); 

     if(flag) 
      printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree); 
     else 
      printf("not found\n"); 

    } 

    return 0; 
} 
+6

Che tipo di errore? –

+2

E l'errore è? .. – kan

+0

su linux il suo errore di ricezione :: âMEMORYSTATUSEXâ non è stato dichiarato in questo ambito, âstatexâ non è stato dichiarato in questo ambito e in windows :: errore C3861: "popen": identificatore non trovato ... simile come questo .... cosa dovresti fare? – Ronin

risposta

35

è generalmente fatta in questo modo (più o meno):

#ifdef _WIN32 
#include <windows.h> 
#include <stdio.h> 
#include <tchar.h> 

#define DIV 1048576 
#define WIDTH 7 
#endif 

#ifdef linux 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#endif 


int main(int argc, char *argv[]) 
{ 
#ifdef _WIN32 
MEMORYSTATUSEX statex; 
    statex.dwLength = sizeof (statex); 
    GlobalMemoryStatusEx (&statex); 

    _tprintf (TEXT("There is %*ld %% of memory in use.\n"), 
      WIDTH, statex.dwMemoryLoad); 
#endif 

#ifdef linux 
char cmd[30]; 
int flag = 0; 
FILE *fp; 
char line[130];  
int TotalMem, TotalFree, TotalUsed; 

flag=0; 
memcpy (cmd,"\0",30); 
sprintf(cmd,"free -t -m|grep Total");   
fp = popen(cmd, "r");  
while (fgets(line, sizeof line, fp)) 
{ 
    flag++; 
    sscanf(line,"%*s %d %d %d",&TotalMem, &TotalUsed, &TotalFree); 
} 
pclose(fp); 

if(flag) 
    printf("TotalMem:%d -- TotalUsed:%d -- TotalFree:%d\n",TotalMem,TotalUsed,TotalFree); 
else 
    printf("not found\n"); 
#endif 

    return 0; 
} 

questo modo, solo il codice per linux verrà compilato su una piattaforma Linux e solo il codice Windows verrà compilato su una piattaforma Windows.

+2

thankzzz .... u r un salva-vita. – Ronin

+0

@Cicada per compilare questo codice di modifica int memTotal, memFree, memUsed; su int TotalMem, TotalFree, TotalUsed; –

16

Si dovrebbe usare la stessa #ifdef invece di if(OS_Windows) logica nel codice:

#ifdef __unix__   
... 
#elif defined(_WIN32) || defined(WIN32) 

#define OS_Windows 

#endif 

int main(int argc, char *argv[]) 
{ 
#ifdef OS_Windows 
/* Windows code */ 
#else 
/* GNU/Linux code */ 
#endif  
} 
6

Si stanno confondendo le variabili (che esistono in fase di esecuzione) con i simboli del preprocessore (che esistono solo durante la compilazione).

Dopo aver fatto una cosa del genere #define OS_Windows 1, non è possibile utilizzare le OS_Windows simbolo come variabile e metterlo dentro if() s ... Voglio dire, è possibile, ma sarà esteso durante la compilazione di if (1).

Per un progetto multipiattaforma, Devi usare #if o #ifdef fare in modo che il compilatore sceglie una corretta parte di codice per un determinato sistema operativo e compila solo quello.

Qualcosa di simile:

void openWindow() { 
#if OS_Windows 
    // windows-specific code goes here 
#else 
    // linux-specific code 
#endif 
} 
+0

>> "_it sarà espanso durante la compilazione a' if (1) '_" Sì, o a 'if (0)' se 'OS_Windows' è stato definito a 0. La _main question_ è il motivo per posticipare questa ramificazione per l'esecuzione -tempo, se sappiamo già in fase di compilazione, di quale ramo abbiamo bisogno. Quindi con '# if'-costruzioni potremmo evitare tempi extra di esecuzione e codice extra – user1234567

2

tua strategia di base è profondamente sbagliata.

Utilizzando if se nella funzione principale si seleziona quale blocco di codice da eseguire in RUNTIME. Quindi, anche se la compilazione per Unix il compilatore deve ancora compilare il codice per Windows (cosa che non riesce a fare perché i file header non sono inclusi) e viceversa.

È invece necessario #if che verrà valutato in fase di compilazione e non tenterà di compilare codice irrilevante.

Quindi, in sostanza, è necessario comprendere che se valuta il proprio definire un'espressione in fase di esecuzione mentre #if valuta il valore della costante predefinita in fase di compilazione.

+1

Qualsiasi compilatore ottimizzante degno di questo nome rimuoverà un blocco' if (0) '. – Dave

+1

@Dave Sfortunatamente ciò non aiuta molto perché il compilatore non può ottimizzare nulla che non verrà compilato per iniziare con – Elemental

+0

Ciò che intendo è che il problema non è rappresentato da simboli estranei; sono inesistenti – Dave

5

Qui vedo molte soluzioni diverse, il che mi mette a disagio ... E se lavorano su Linux ma non su Windows o su Windows ma non su Linux? Cosa succede se funzionano solo su alcuni compilatori? Ecc

così ho trovato questo link, che mi piace: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

Sembra che questi sono i migliori (utilizzando #ifdef, #endif, etc.):

  • _WIN32 per Windows a 32 bit
  • _WIN64 per Windows a 64 bit
  • __unix__ per Unix
Problemi correlati