c++跨平臺技術學習(三)--使用標準API

Posix.1 API定義了大量的函數,在各方面的功能都很豐富,下面對其進行介紹

System V接口定義

它是一份描述了AT&T UNIX System V操作系統的文檔,與POSIX.1保持一致,是它的一個超集。SVID由基礎系統和擴展定義,它只定義了C編程接口,沒有定義任何用戶級別的命令,基礎系統更進一步細分幾個類別

基礎OS服務程序

它由以下三個子類組成:

  • 第一組:包含了完整基礎OS服務程序核心功能的函數,有150個左右。函數如mkdir、malloc、popen、sigaction、fopen等都可以在這裏找到
  • 第二組:包含了以下低級的操作系統函數:close、creat、dlclose、dlerror、dlopen、dlsysm、execl、execle、execlp、execv、execve、execvp、fork、lseek、mount、open、read、readv、umount、write、和writev
  • 第三組:只有_exit和sync

數學函數

這個類別包含了將近40個函數支持各種數學操作,如abs、floor、ceil、sin、cos、tan、log、log10、pow和sqrt。

字符串和字符的處理

有超過150個函數,包括str族(strok、strncat等);ctype函數如toascii、tolower、isupper和isdigit,轉換函數如asctime、atof、atol和atoi;多字節和寬字符函數如mblen、mbrtow、wscncpy、wcsstr和wcsncpy;以及men族函數,包括memchr、memcpy、memset和memmove

網絡函數

大部分開發人員都知道Berkeley sockets API在網絡應用中的角色,但是socket、bind、listen、accept、connect等函數並不屬於SVID。取而代之的是XTI(X/Open Transport Interface)是由X/Open開發的TLI(Trasnport Layer Interface)的一個擴展。TLI則是由AT&T開發的一套API。在舊版本的mac OS上寫過網絡代碼的mac os工程師或許會對這些函數比較熟悉,因爲TLI和XTI曾經是OpenTransport網絡API的基礎。TLI/XTI的一個優點是傳輸無關的。

通用庫函數

這個類別包含了100多個能在ISO標準C庫裏找到的函數,包括glob、drand48、nrand48、bsearch、catgets、gets、puts、fgets、fputs、getopt、printf、putchar、getc、sprintf、sscanf

XPG、X/Open和Single UNIX Specification

XPG是由X/Open開發的一系列標準,BSD(Berkeley Standard Distribution)包括sockets以及相關API。

在GCC裏使用標準支持

編譯器標誌

第一個要在GCC中加的參數或許就是-ansi和-pendantic。-ansi參數令GCC嚴格遵守ANSI/ISO C語言標準,並且移除所有的GNU擴展。-pendantic參數則令GCC拒絕接受任何不符合標準的代碼。省略這個參數不會禁止你在調用定義在C庫裏符合標準的函數,但是它能幫助你避免誤用API,例如像庫裏(庫裏躺槍)的函數傳遞了錯誤類型的參數。

-Wall參數一定要在命令行的參數裏,編寫可移植代碼第一步就是編寫正確的代碼

頭文件

接下來就是要包含定義了調用函數的頭文件,如果使用率-ansi和-pendantic標誌的話,這就是必須的步驟。可以通過終端窗口或者Google來查看man(1)page確定應該包含哪些頭文件,通常在Synopsis一節中找到

ATOF(3) System Library Fuctions Manual ATOF(3)

NAME
 atof -convert ASSII string to double
LIBRARY
Standard C Library(libc,-lc)
SYNOPSIS
#inclue<stdlib.h>
double
atof(const char * nptr)

所以要使用atof()函數,就需要以如下的方式包含

#include<stdlib.h>

在C++裏也ok,但是C++推薦的用法是隻包含文件名而去除後綴.h.如下

#include<cstlib>

GCC提供的頭文件不需要包含多次,而且包含順序也麼有影響。

命令行參數-ansi令只接受ISO/ANSI的特性。若要使用POSIX或SVID支持的接口,你需要打開一些GCC定義的宏才行,這些宏應該在每個源文件的開頭指定任何頭文件之前定義。這樣宏就能被C預處理器正確處理,進而影響到GNU提供的頭文件裏哪些函數、常量、宏的聲明和定義可以在你的代碼裏出現。還可以在Makefile裏用-D命令行選項來定義這些宏,不過GNU文檔推薦的方式是直接在源文件裏包含它們。

下面的代碼來自

typedef void *DIR

#define _POSIX_SOURCE 1 … #include<dirent.h>

那麼下列語句就回定義DIR類型

不然DIR就會在#else語句裏定義:

#include<sys/dirent.h>
#ifdef _POSIX_SOURCE
typedef void *DIR;
#else
#define d_ino d_fileno
#define DIRBLKSIZ 1024
typedef struct _dirdesc {
    int dd_fd;
    long dd_loc;
    long dd_size;
    char * dd_buf;
    int dd_len;
    long dd_seek;
    long dd_rewind;
    int dd_flags;

}DIR;
#define drifd(dirp)((dirp)->dd_fd)
#define DIF_HIDEW 0x0001
#define DTF_NODUP 0x0002
#define DTF_REWIND 0x0004
#define _DTF_READALL Ox0008
#ifndef NULL
#define NULL 0
#endif
#endif

這是和之前討論的標準相關的GCC所支持的宏的列表

  • _POSIX_SOURCE:定義它會打開POSIX.1標準和所有ISO C的工具。如果把_POSIX_SOURCE定義成爲一個正整數,那麼可以將其忽略

  • _POSIX_C_SOURCE:把它定義爲一個大於1的整數,符合1990年POSIX標準;定義爲2符合POSIX.2標準,定義爲大於199309L的整數,包含所有1993年POSIX.1b標準的功能

  • _BSD_SOURCE:被定義後,允許訪問4.3 BSD UNIX、ISO C、POSIX.1和POSIX.2的功能。定義這個宏後,當4.3BSD定義和POSIX發生衝突1時,會優先採用4.3BSD的定義。必須在鏈接應用程序是使用-lbsd-compat參數在普通C函數庫裏搜索他們之前解決BSD函數的問題

  • _SVID_SOURCE:定義它可以包含SVID系列的功能以及由ISO C、POSIX和X/Open標準提供的功能

  • _XOPEN_SOURCE:打開X/Open Portability Guide定義的功能,以及包含由_POSIX_SOURCE和_POSIX_C_SOURCE宏定義的函數。值爲500時,還包含Single UNIX Specification第2版裏的新功能

  • _ISOC99_SOURCE:C99標準

  • _GNU_SOURCE:包括之前所有的內容。如果有任何POSIX.1與BSD發生衝突的內容,POSIX的定義將會優先於BSD。由於GNU擴展是不可移植的,所以應該避免使用這個宏

微軟Runtime Library對POSIX的支持

創建文件的API展示了Win2、POSIX和Windows NT系統如何協同工作的。在Win32下,創建文件的函數是CreateFile,在POSIX API裏則是creat()函數。這兩個函數功能一模一樣,把接受的參數按需要處理後,再傳給Windows NT的NtCreateFile()函數

NtCreateFile(



  OUT PHANDLE             FileHandle,
  IN ACCESS_MASK          DesiredAccess,
  IN POBJECT_ATTRIBUTES   ObjectAttributes,
  OUT PIO_STATUS_BLOCK    IoStatusBlock,
  IN PLARGE_INTEGER       AllocationSize OPTIONAL,
  IN ULONG                FileAttributes,
  IN ULONG                ShareAccess,
  IN ULONG                CreateDisposition,
  IN ULONG                CreateOptions,
  IN PVOID                EaBuffer OPTIONAL,
  IN ULONG                EaLength );

不過上面代碼有點系小問題。POSIX的creat()並不存在與微軟的運行庫中,而是以_creat()形式出現的。在微軟RTL裏的POSIX函數都是這種命名規則,_dup()、_fdopen()等。這麼做的意思是如果不使用一些宏和封裝來吧一個版本里的函數映射到另一個版本上的話,這些函數都是不可移植的。

微軟RTL的文檔爲open函數添加了O_BINARY、O_TEXT和其他一些沒有在POSIX定義的標誌位,它還不支持O_SHILOCK和O_EXLOCK。

還有一些爲Mac OS X和Linux編寫的POSIX代碼無須修改就可以移植到Windows上的。最好還是儘量用通用的部分編寫代碼,並且充分測試保證運行的兼容性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章