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上的。最好还是尽量用通用的部分编写代码,并且充分测试保证运行的兼容性

posted on 2016-10-12 17:48  爱你一万年123  阅读(252)  评论(0编辑  收藏  举报

导航