您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > C/C++资料 > C&C++跨平台编码教程(概论)
C/C++跨平台编码概论关于预编译宏#pragmaWindows•Windows使用的#pragmaonce来防止头文件重复引用Windows/Linux•在跨平台的代码中,我们使用•#ifndef…#define…#endif宏来实现这个功能#includeWindows•Windows中的#include中可以使用“\”,而且路径名称大小写并无区别。•例如下面的写法是等效的:•#include“..\\ACE.h”•#include“../ACE.h”•#include“..\\ace.h”Windows/Linux•跨平台的代码中,#include中只能使用“/”(同网址中使用的相同),而且路径名、文件名都是大小写敏感的:•#include“..\\ACE.h”(错误)•#include“ACE.h”与#include”ace.h”不等效开发工具Windows•Windows中我们通常都使用VisualStudio系列的开发工具来开发程序代码Windows/Linux•跨平台的代码也可以使用VisualStudio系列的开发工具来开发,这与Windows程序一样。•不同的是我们并不使用MS提供的SDK(比如MFC),而是使用C++标准库(VC已支持)和一些支出跨平台的SDK(比如ACE)提供的库字符串处理Windows•Windows中,我们使用CString来处理字符串。Windows/Linux•跨平台代码中,我们使用C++标准库的std::string来处理字符串,这个类对应的头文件是string。•C++标准库还提供了流操作来处理字符串,比如std::stringstream,这个类对应的头文件是sstream。多语言处理MVC原则•MVC将系统分成了原始数据层,控制/映射层和视图层。在这三个层次中,只有原始数据层和视图层才可以处理多语言的问题,控制/映射层不应该介入此问题。I/O处及时处理原则•当我们需要进行字符集转换时,请在I/O附近就完成这一功能。•所谓的I/O附近是指跨越模块、系统、文件读写操作等边界的附近。•这样做可以让模块内部、系统内部的其它代码免于字符串转换的负担,简化系统维护的难度和定位问题的难度。无论是否要跨平台,在处理文字的时候,我们都会遇到多种字符集的问题。这里我们提供两条原则来解决这一问题:基本变量类型Windows•Windows下,我们使用的是MS提供的一套变量类型,比如DWORD,WORD…Windows/Linux•跨平台方式下,我们使用的是支持跨平台的SDK提供的变量类型。•以ACESDK为例,我们使用的变量类型是ACE_UINT8,ACE_UINT32…指针32位系统•在32位系统中,有时我们需要将指针转换成整形变量。比如将指针用作map的key。•如果我们要使用整形变量保存指针,使用int或long就行了。32位/64位系统•在跨平台时,我们使用typedef来解决这个问题。•比如在基于ACESDK的开发中,我使用了如下方法:#ifndef_ACE_POINTER_KEY_TYPE_#define_ACE_POINTER_KEY_TYPE_#ifndefACE_WIN64typedefACE_UINT32ACE_PointerKey;//For32bitsOS.#elsetypedefACE_UINT64ACE_PointerKey;//For64bitsOS.#endif#endif//_ACE_POINTER_KEY_TYPE_listWindows•Windows中,我们使用MS提供的CList类及其子类。Windows/Linux•在跨平台时,我们使用的是C++标准库提供的std::list类。mapWindows•Windows中我们使用MS提供的CMap类及其子类。•其实MS的CMap类严格意义上说只能算是一个哈希表,算不上树结构。Windows/Linux•在跨平台时,我们使用C++标准库提供的std::map类。线程Windows•Windows中,MS提供了CWinThread和CThread两个类来创建线程Windows/Linux•在跨平台时,由于线程、互斥锁、信号都是与OS相关的,所以我们只能使用支持跨平台的SDK提供的类库。•比如在ACE中,我们可以使用ACE_Thread::spawn来创建线程。互斥锁Windows•Windows中,MS提供了CCritialSection,CMutex等互斥锁。Windows/Linux•在跨平台时,由于线程、互斥锁、信号都是与OS相关的,所以我们只能使用支持跨平台的SDK提供的类库。•比如在ACE中,我们使用ACE_Thread_Mutex、ACE_Recursive_Thread_Mutex等互斥锁。•为了避免像MS中那样忘了释放互斥锁,ACE还提供了ACE_GUARD宏来自动完成释放操作。信号Windows•Windows中,MS提供CreateEvent函数来创建信号,WaitForSingleObject等函数来使用信号。Windows/Linux•在跨平台时,由于线程、互斥锁、信号都是与OS相关的,所以我们只能使用支持跨平台的SDK提供的类库。•比如在ACE中,我们使用ACE_Auto_Event和ACE_Manual_Event来实现这些功能。动态分配内存Windows•Windows中,我们使用new/delete或者malloc/realloc/free来动态分配、释放内存。•其中,无论是new一个数组还是一个变量,我们都可以使用delete来释放内存Windows/Linux•在跨平台中,我们也是使用new/delete或者malloc/realloc/free来动态分配、释放内存。•不过,与Windows不同,new一个数组必须使用delete[]来释放,new一个变量必须使用delete来释放。否则在Linux中会导致堆栈异常。字节对齐Windows•Windows中我们使用#pragmapack宏来声明字节对齐的方式。Linux•Linux中我们使用__attribute__((aligned(n)))和__attribute__((packed))来声明字节对齐的方式。•我们通过宏定义+WIN32宏来实现代码跨平台:#ifdefWIN32#pragmapack(push)#pragmapack(4)#endif#ifndefPRAGMA_PACK_4#ifdefWIN32#definePRAGMA_PACK_4#else#definePRAGMA_PACK_4__attribute__((aligned(4)))#endif//WIN32#endif//PRAGMA_PACK_4structtagCOMMON_STREAM_DATA{ACE_UINT32length;ACE_UINT8data[0];}PRAGMA_PACK_4;namespaceWindows•Windows内核与Linux不同,同名的两个类我们可以封装在不同的动态库中,通过动态加载就可以同时使用了。Linux•Linux中,同名的两个类即使封装在两个不同的动态库中,内核也会认为是同一个类。只要任何一个类被内核加载了,另一个同名类便再无机会。这往往会导致程序在Linux环境下异常。•因此,跨平台的代码必须使用namespace来预防同名函数、变量和类。•我们推荐的命名原则是:namespace公司{namespace子系统{namespace模块{….源代码文件Windows•VisualStudio工具对源代码文件的结束符并无要求Linux•Linux编译环境要求源代码文件必须以换行符结束(文件末尾必须是换行符),否则在编译时会提示warning。•因此,我们要求跨平台的代码的文件末尾必须是换行符。资源文件Windows•VisualStudio为我们提供了资源文件的开发、编辑工具和界面。Linux•Linux开发工具并无资源一说。•因此,跨平台的开发必须将资源文件保存在能够跨平台的文件中,比如XML文件。•在设计程序时,必须设计资源的调用功能。编译配置Windows•Windows下的工程编译配置是在VisualStudio的工程属性配置中就可以完成的。Linux•Linux的编译参数只能在Makefile中进行配置。Makefile使用的是脚本,不过我们可以使用Qt3或Qt4Creator来帮助我们编写Makefile脚本。•做法就是用Qt创建一个C++工程,将工程的头文件、源文件都添加到工程中去,然后使用qmake命令就可以自动生成Makefile文件了。预编译头文件Windows•Windows下的工程编译配置可以使用预编译头文件,而且VisualStudio创建的默认工程通常都使用预编译头文件。Windows/Linux•跨平台的代码不使用预编译头文件,因为Linux下没有预编译头文件的概念。全局的宏都在Makefile中就可以定义。•Windows下的全局宏定义也可以在VisualStudio中实现。代码移植基于ACESDK的代码移植•ACESDK中将操作系统相关的操作都封装在ACE_OS命名空间相关的代码中。因此,通过裁剪、修改这部分代码,我们就可以将ACESDK移植到不同的操作系统上。ACESDK给我们的启示•在设计系统时,我们也需要这样,将那些与OS、外设相关的功能封装成独立的模块,通过标准的接口调用。•常见的这类型的外设包括网络传输、外设驱动等。使用ACESDK•ACESDK是平台相关的SDK,在使用之前必须要先编译。在编译过程中,ACESDK会检查OS的配置来自动完成兼容性宏设置。•编译完成后,我们需要将ACESDK的路径添加到我们的开发工具头文件路径和库文件路径中。•在这些操作完成后,只要我们在工程代码中使用#include“ACE.h”,我们就可以使用ACESDK提供的类库和功能了。•ACESDK的初始化操作ACE:init()和卸载操作ACE::fini()只需要在可执行程序的初始化和卸载操作中添加,无需在动态库中添加。如果在动态库中使用,一旦动态库提前卸载,那么ACE环境就被异常卸载掉了。编程帮助文档Windows•Windows中,MS提供了MSDN。在MSDN中,我们除了可以查阅MS专门提供的SDK帮助外,还能供查阅C/C++提供的SDK的资料。这是我们查阅资料的一个重要来源。Linux•Linux编程相关的资料比较分散,但我们可以通过如下途径找到:•百度搜索;•OS发布同时提供的编程资料,通常可以在相关网站上找到;•ACESDK的资料可以在ACESDK官网或压缩包中找到;•现有的代码。查看已有的代码也是一种查找资料的途径。调试日志Windows•由于开发环境和运行环境都在Windows上,所以代码中可以使用中文的调试信息。Windows/Linux•通常开发环境与运行环境不同,所以如果在代码中使用中文的调试信息,很容易得到的是乱码。•调试信息只能使用英文。
本文标题:C&C++跨平台编码教程(概论)
链接地址:https://www.777doc.com/doc-7027140 .html