2011-05-11 79 views
17

我試圖讓編程C中的Mac OS X版本搜索一段時間後獲得在Mac OS X操作系統的版本我想這個代碼:用標準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返回LD錯誤:

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

我缺少什麼?你怎麼做到這一點?

我也發現這個片段

[[NSProcessInfo processInfo] operatingSystemVersionString] 

但我不知道怎麼寫,在C.

+0

嗯,這是一個鏈接錯誤,所以我想你還沒有告訴鏈接器去尋找合適的系統庫... //用方括號中的比特看起來是在Objective-C – dmckee

+0

你知道我會如何將它翻譯成C? – Jessica

回答

16

你通過適當的框架,以海灣合作委員會,以使CoreServices

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

下面的代碼應該在可預見的未來工作搞清楚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

這可以用較少的工作完成。但是sysctl是你想要的BSD功能。 http://www.unix.com/man-page/FreeBSD/3/sysctl/ – uchuugaka

+3

你在'#if 1 == 1'處失去了我。嚴重的是,這麼多的代碼並不構成答案,並且有如此豐富的sysctl選擇器,你可以告訴我們哪一個是合適的。 – Potatoswatter

+0

如果uchuugaka知道如何用較少的工作做到這一點,那麼請分享! :) 我不知道什麼Potatoswatter意思是在1 == 1迷路,我用它來定義測試變量,它更少打字將1更改爲0,並僞造測試。 – McUsr

1

這裏的當前版本是一個與「少作」,爲家庭項目足夠好(靜態分配緩衝區,忽略錯誤)。適用於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 ; 
}