2011-05-11 8 views
17

Sto cercando di ottenere la versione di Mac OS X di programmazione in C. Dopo aver cercato per un po 'ho provato questo codice:Ottenere la versione del sistema operativo Mac OS X utilizzando standard di C

#include <CoreServices/CoreServices.h> 

int GetOS() 
{ 
    SInt32 majorVersion,minorVersion,bugFixVersion; 

    Gestalt(gestaltSystemVersionMajor, &majorVersion); 
    Gestalt(gestaltSystemVersionMinor, &minorVersion); 
    Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); 

    printf("Running on Mac OS X %d.%d.%d\n",majorVersion,minorVersion,bugFixVersion);  

    return 0; 
} 

XCode restituisce un errore di LD:

Undefined symbols for architecture x86_64: "_Gestalt", referenced from: _GetOS in main.o

che cosa mi manca? Come fai a fare questo?

ho trovato anche questo frammento

[[NSProcessInfo processInfo] operatingSystemVersionString] 

Ma non ho idea di come scrivere che in C.

+0

Beh, si tratta di un errore di linker, quindi suppongo che non ti ho detto il linker a cercare la libreria sistema giusto ... // Il bit con le parentesi quadre sembra essere in Objective-C – dmckee

+0

Sai come lo tradurrei in C? – Jessica

risposta

16

Sei passato il quadro adeguato per GCC al fine di consentire CoreServices?

% gcc -framework CoreServices -o getos main.c 
1

Il seguente codice dovrebbe funzionare nel prossimo futuro per capire l'attuale versione di Mac OS X.

/* McUsr put this together, and into public domain, 
    without any guarrantees about anything, 
    but the statement that it works for me. 
*/ 

#if 1 == 1 
#define TESTING 
#endif 

#include <sys/param.h> 
#include <sys/sysctl.h> 
#include <errno.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

struct osver { 
    int minor; 
    int sub; 
} ; 
typedef struct osver osxver ; 
void macosx_ver(char *darwinversion, osxver *osxversion) ; 
char *osversionString(void) ; 

#ifdef TESTING 
int main(int argc, char *argv[]) 
{ 
    osxver foundver; 
    char *osverstr= NULL ; 
    osverstr=osversionString() ; 
    macosx_ver(osverstr, &foundver) ; 
    printf("Mac os x version = 10.%d.%d\n",foundver.minor,foundver.sub); 
    free(osverstr); 
    return 0; 
} 
#endif 
char *osversionString(void) { 
    int mib[2]; 
    size_t len; 
    char *kernelVersion=NULL; 
    mib[0] = CTL_KERN; 
    mib[1] = KERN_OSRELEASE; 

    if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { 
     fprintf(stderr,"%s: Error during sysctl probe call!\n",__PRETTY_FUNCTION__); 
     fflush(stdout); 
     exit(4) ; 
    } 

    kernelVersion = malloc(len); 
    if (kernelVersion == NULL) { 
     fprintf(stderr,"%s: Error during malloc!\n",__PRETTY_FUNCTION__); 
     fflush(stdout); 
     exit(4) ; 
    } 
    if (sysctl(mib, 2, kernelVersion, &len, NULL, 0) < 0) { 
     fprintf(stderr,"%s: Error during sysctl get verstring call!\n",__PRETTY_FUNCTION__); 
     fflush(stdout); 
     exit(4) ; 
    } 

    return kernelVersion ; 
} 

void macosx_ver(char *darwinversion, osxver *osxversion) { 
/* 
    From the book Mac Os X and IOS Internals: 
    In version 10.1.1, Darwin (the core OS) was renumbered from v1.4.1 to 5.1, 
    and since then has followed the OS X numbers consistently by being four 
    numbers ahead of the minor version, and aligning its own minor with the 
    sub-version. 
*/ 
    char firstelm[2]= {0,0},secElm[2]={0,0}; 

    if (strlen(darwinversion) < 5) { 
     fprintf(stderr,"%s: %s Can't possibly be a version string. Exiting\n",__PRETTY_FUNCTION__,darwinversion); 
     fflush(stdout); 
     exit(2); 
    } 
    char *s=darwinversion,*t=firstelm,*curdot=strchr(darwinversion,'.'); 

    while (s != curdot) 
     *t++ = *s++; 
    t=secElm ; 
    curdot=strchr(++s,'.'); 
    while (s != curdot) 
     *t++ = *s++; 
    int maj=0, min=0; 
    maj= (int)strtol(firstelm, (char **)NULL, 10); 
    if (maj == 0 && errno == EINVAL) { 
     fprintf(stderr,"%s Error during conversion of version string\n",__PRETTY_FUNCTION__); 
     fflush(stdout); 
     exit(4); 
    } 

    min=(int)strtol(secElm, (char **)NULL, 10); 

    if (min == 0 && errno == EINVAL) { 
     fprintf(stderr,"%s: Error during conversion of version string\n",__PRETTY_FUNCTION__); 
     fflush(stdout); 
     exit(4); 
    } 
    osxversion->minor=maj-4; 
    osxversion->sub=min; 
} 
+0

Questo potrebbe essere fatto con meno lavoro. Ma sysctl è la funzione BSD che desideri. http://www.unix.com/man-page/FreeBSD/3/sysctl/ – uchuugaka

+3

Mi hai perso a '#if 1 == 1'. Seriamente, questo codice non costituisce una risposta, e ci sono una tale abbondanza di selettori di sysctl che potresti semplicemente dirci quale è appropriato. – Potatoswatter

+0

Se uchuugaka sa come farlo con meno lavoro, per favore condividi! :) Non ho idea di cosa significhi Potatoswatter perdersi a 1 == 1, lo uso per definire la variabile di test, è meno digitante per cambiare da 1 a 0 e falsificare il test. – McUsr

1

Ecco uno con "meno lavoro", abbastanza buono per i progetti di casa (staticamente buffer assegnati, ignorando errori). Funziona per me in OS X 10.11.1.

#include <stdio.h> 

/*! 
    @brief Returns one component of the OS version 
    @param component 1=major, 2=minor, 3=bugfix 
*/ 
int GetOSVersionComponent(int component) { 
    char cmd[64] ; 
    sprintf(
      cmd, 
      "sw_vers -productVersion | awk -F '.' '{print $%d}'", 
      component 
    ) ; 
    FILE* stdoutFile = popen(cmd, "r") ; 

    int answer = 0 ; 
    if (stdoutFile) { 
     char buff[16] ; 
     char *stdout = fgets(buff, sizeof(buff), stdoutFile) ; 
     pclose(stdoutFile) ; 
     sscanf(stdout, "%d", &answer) ; 
    } 

    return answer ; 
} 

int main(int argc, const char * argv[]) { 
    printf(
      "Your OS version is: %d.%d.%d\n", 
      GetOSVersionComponent(1), 
      GetOSVersionComponent(2), 
      GetOSVersionComponent(3) 
      ) ; 

    return 0 ; 
} 
Problemi correlati