编写跨平台的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