2011-12-29 33 views
33

Estoy escribiendo un programa multiplataforma. Quiero que este programa se ejecute tanto en Windows como en Linux, así que tengo dos segmentos de código diferentes para las dos plataformas. Si el sistema operativo es Windows, quiero que se ejecute el primer segmento de código; si es Linux, entonces quiero que se ejecute el segundo segmento de código.Detectar Windows o Linux en C, C++

Así que escribí el siguiente código, pero se produce un error al generar tanto en Windows como en Linux. ¿Qué debo hacer para resolverlo?

#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

¿Qué tipo de error? –

+2

Y el error es? .. – kan

+0

en linux es un error: âMEMORYSTATUSEXâ no se ha declarado en este ámbito, âstatexâ no se ha declarado en este ámbito y en Windows :: error C3861: 'popen': identificador no encontrado ... similar a esto .... ¿qué hacer? – Ronin

Respuesta

35

por lo general es hecho así (más o menos):

#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; 
} 

De esta manera, sólo se el código para Linux se compilará en una plataforma de Linux, y solo el código de Windows se compilará en una plataforma de Windows.

+2

thankzzz .... u r a life-saver. – Ronin

+0

@Cicada para compilar este código change int memTotal, memFree, memUsed; a int TotalMem, TotalFree, TotalUsed; –

16

Se debe utilizar la misma #ifdef en lugar de if(OS_Windows) lógica en el código:

#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

Estás confundiendo variables (que existen en tiempo de ejecución) con símbolos de preprocesador (que solo existen durante la compilación).

Después de hacer algo así como #define OS_Windows 1, no puede utilizar los símbolos OS_Windows como una variable y ponerlo dentro de if() s ... Es decir, se puede, pero se ampliará durante la compilación de if (1).

Para un proyecto multiplataforma, que tienen que utilizar #if o #ifdef para asegurarse de que el compilador elige una parte correcta de código para un sistema operativo determinado y compila sólo eso.

Algo así como:

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

>> "_it se expandirá durante la compilación a' if (1) '_" Sí, o a 'if (0)' si 'OS_Windows' se definió a 0. La _main question_ es la razón por la que posponer esta ramificación para ejecutar -tiempo, si ya sabemos en tiempo de compilación, qué rama necesitamos. Por lo tanto, mediante construcciones '# if' podríamos evitar el código extra de tiempo de ejecución y extra – user1234567

2

Su estrategia básica es profundamente defectuoso.

Al utilizar la función si en la función principal, está seleccionando qué porción de código ejecutar en RUNTIME. Por lo tanto, incluso si se compila para Unix, el compilador aún tiene que compilar el código para Windows (que no está haciendo porque los archivos de encabezado no están incluidos) y viceversa.

Necesita en su lugar #if que se evaluará en tiempo de compilación y no intentará compilar código irrelevante.

Entonces, en esencia, debe comprender que si evalúa su definición como una expresión en tiempo de ejecución, mientras que #if evalúa el valor de la constante predefinida en tiempo de compilación.

+1

Cualquier compilador optimizado que merezca la pena eliminará un bloque' if (0) '. – Dave

+1

@Dave Desafortunadamente eso no ayuda porque el compilador no puede optimizar nada que no compilará para comenzar con – Elemental

+0

Lo que quiero decir es que el problema no son los símbolos extraños; es inexistente. – Dave

5

Veo muchas soluciones variadas aquí, lo que me incomoda ... ¿Qué pasa si funcionan en Linux pero no en Windows o en Windows pero no en Linux? ¿Y si solo funcionan en algunos compiladores? Etc.

así que encontré este enlace, que me gusta: http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system

Parece que estos son mejores (usando #ifdef, #endif, etc.):

  • _WIN32 para Windows de 32 bits
  • _WIN64 para Windows de 64 bits
  • __unix__ para Unix
Cuestiones relacionadas