编写跨平台的C ++代码(Windows,Linux和Mac OSX)
这是我第一次尝试在C ++中编写任何有点复杂的东西,我试图构build一个共享库,我可以从Objective-C和.NET应用程序(可以,那部分后来…)
我有的代码是 –
#ifdef TARGET_OS_MAC // Mac Includes Here #endif #ifdef __linux__ // Linux Includes Here #error Can't be compiled on Linux yet #endif #ifdef _WIN32 || _WIN64 // Windows Includes Here #error Can't be compiled on Windows yet #endif #include <iostream> using namespace std; bool probe(){ #ifdef TARGET_OS_MAC return probe_macosx(); #endif #ifdef __linux__ return probe_linux(); #endif #ifdef _WIN32 || _WIN64 return probe_win(); #endif } bool probe_win(){ // Windows Probe Code Here return true; } int main(){ return 1; }
我有一个编译器警告,只是untitled: In function 'bool probe()':untitled:29: warning: control reaches end of non-void function
– 但我也非常感谢任何信息或资源人们可以build议如何写这种代码更好….
我将解决这个特定的function:
bool probe() { #ifdef TARGET_OS_MAC return probe_macosx(); #elif defined __linux__ return probe_linux(); #elif defined _WIN32 || defined _WIN64 return probe_win(); #else #error "unknown platform" #endif }
以这种方式编写if-elif-else链,可以消除错误,因为如果没有有效的return语句或者碰到#error就不可能编译。
(我相信WIN32是为32位和64位Windows定义的,但是如果不查看它,我无法确定地告诉你,这将简化代码。)
不幸的是,你不能使用#ifdef _WIN32 || _WIN64:有关示例错误消息,请参阅http://codepad.org/3PArXCxo 。 您可以像上面所做的那样,使用特定的仅用于预处理的定义的运算符。
关于根据function或整个文件(如build议 )分割平台,你可能会也可能不想这样做。 这将取决于您的代码的细节,例如平台之间共享多less,以及您(或您的团队)最适合保持function同步等问题。
此外,您应该在构build系统中处理平台select,但这并不意味着您不能使用预处理器:为每个平台使用有条件定义的macros(由makefile或build system)。 事实上,这是模板和内联函数通常最实际的解决scheme,这使得它比试图消除预处理器更加灵活。 它与整个文件方法很好地结合在一起,所以你仍然在适当的地方使用它。
您可能需要一个单独的configuration头文件,将所有各种编译器和平台特定的macros转换为您所控制的众所周知和理解的macros。 或者,您可以在您的编译器命令行中添加-DBEAKS_PLAT_LINUX(通过您的构build系统)来定义该macros(记住为macros名称使用前缀)。
而不是重复自己,再一次写同样的#ifdef ….行,你可能更好的是在头文件中声明probe()方法,并提供三个不同的源文件,每个平台一个。 这也有好处,如果你添加一个平台,你不必修改所有的现有的来源,但只是添加新的文件。 使用您的构build系统来select适当的源文件。
示例结构:
include/probe.h src/arch/win32/probe.cpp src/arch/linux/probe.cpp src/arch/mac/probe.cpp
警告是因为probe()不返回一个值。 换句话说,三个#ifdefs都不匹配。
在编译代码时,似乎没有TARGET_OS_MAC
, __linux__
TARGET_OS_MAC
, __linux__
或_WIN64
被定义。
所以它就像你的代码是:
bool probe(){ }
这就是为什么编译器抱怨到达非void函数的末尾。 没有return
条款。
另外,对于更一般的问题,下面是我开发多平台/架构软件/库时的指导原则:
避免特定情况。 尝试编写与操作系统无关的代码。
当处理系统特定的东西时,尝试把东西包装成“不透明”的类。 例如,如果您正在处理文件(Linux和Windows上的不同API),请尝试创build一个File
类,该类将embedded所有逻辑并提供一个公共接口,无论操作系统如何。 如果某个function在某个操作系统上不可用,请处理:如果该function对于某个特定的操作系统没有意义,则根本无法做任何事情。
总之: #ifdef
越less越好。 不pipe你的代码是多么便携,在发布之前在每个平台上testing它。
祝你好运 ;)
警告是因为如果没有定义实际定义,那么你的探测function没有return
。 该修复程序被置于默认return
。
__linux__
,为了增加更多内容,除了上面提到的选项以外,编译器已经知道__linux__
和_WIN32
指令,而TARGET_OS_MAC
指令不是,可以用TARGET_OS_MAC
来解决。 资料来源: http : //www.winehq.org/pipermail/wine-patches/2003-July/006906.html