编写跨平台 C++ 代码(Windows、Linux 和 Mac OSX)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3627127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:18:03  来源:igfitidea点击:

Writing cross-platform C++ Code (Windows, Linux and Mac OSX)

c++cross-platform

提问by Lee Hambley

This is my first-attempt at writing anything even slightly complicated in C++, I'm attempting to build a shared library that I can interface with from Objective-C, and .NET apps (ok, that part comes later...)

这是我第一次尝试用 C++ 编写任何稍微复杂的东西,我正在尝试构建一个可以与 Objective-C 和 .NET 应用程序交互的共享库(好吧,那部分稍后会...)

The code I have is -

我的代码是 -

#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;
}

I have a compiler warning, simply untitled: In function ‘bool probe()':untitled:29: warning: control reaches end of non-void function- but I'd also really appreciate any information or resources people could suggest for how to write this kind of code better....

我有一个编译器警告,只是untitled: In function ‘bool probe()':untitled:29: warning: control reaches end of non-void function- 但我也非常感谢人们可以建议如何更好地编写这种代码的任何信息或资源......

采纳答案by Lee Hambley

I'll address this specific 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
}

Writing it this way, as a chain of if-elif-else, eliminates the error because it's impossible to compile without either a valid return statement or hitting the #error.

以这种方式编写它,作为一个 if-elif-else 链,消除了错误,因为如果没有有效的 return 语句或命中 #error 就不可能编译。

(I believe WIN32 is defined for both 32- and 64-bit Windows, but I couldn't tell you definitively without looking it up. That would simplify the code.)

(我相信 WIN32 是为 32 位和 64 位 Windows 定义的,但如果不查一下我就无法明确告诉你。这会简化代码。)



Unfortunately, you can't use #ifdef _WIN32 || _WIN64: see http://codepad.org/3PArXCxofor a sample error message. You can use the special preprocessing-only definedoperator, as I did above.

不幸的是,您不能使用 #ifdef _WIN32 || _WIN64:有关示例错误消息,请参阅http://codepad.org/3PArXCxo。您可以使用特殊的仅预处理定义的运算符,就像我上面所做的那样。



Regarding splitting up platforms according to functions or entire files (as suggested), you may or may not want to do that. It's going to depend on details of your code, such as how much is shared between platforms and what you (or your team) find best to keep functionality in sync, among other issues.

关于根据功能或整个文件(如建议)拆分平台,您可能想也可能不想这样做。这将取决于您的代码的详细信息,例如平台之间共享了多少,以及您(或您的团队)发现什么最能保持功能同步,以及其他问题。

Furthermore, you should handle platform selection in your build system, but this doesn't mean you can't use the preprocessor: use macros conditionally defined (by the makefile or build system) for each platform. In fact, this is the often the most practical solution with templates and inline functions, which makes it more flexible than trying to eliminate the preprocessor. It combines well with the whole-file approach, so you still use that where appropriate.

此外,您应该在构建系统中处理平台选择,但这并不意味着您不能使用预处理器:使用为每个平台(由 makefile 或构建系统)有条件地定义的宏。事实上,这通常是带有模板和内联函数的最实用的解决方案,这使得它比试图消除预处理器更灵活。它与整个文件方法结合得很好,因此您仍然可以在适当的地方使用它。

You might want to have a single config header which translates all the various compiler- and platform-specific macros into well-known and understood macros that you control. Or you could add -DBEAKS_PLAT_LINUX to your compiler command line—through your build system—to define that macro (remember to use a prefix for macro names).

您可能希望有一个单独的配置标头,它将所有各种特定于编译器和平台的宏转换为您控制的众所周知且易于理解的宏。或者您可以将 -DBEAKS_PLAT_LINUX 添加到您的编译器命令行 - 通过您的构建系统 - 以定义该宏(记住使用前缀作为宏名称)。

回答by stijn

instead of repeating yourself and writing the same #ifdef .... lines again, again, and again, you're maybe better of declaring the probe() method in a header, and providing three different source files, one for each platform. This also has the benefit that if you add a platform you do not have to modify all of your existing sources, but just add new files. Use your build system to select the appropriate source file.

与其重复自己并一遍又一遍地编写相同的 #ifdef .... 行,您可能最好在头文件中声明 probe() 方法,并提供三个不同的源文件,每个平台一个。这还有一个好处,即如果您添加一个平台,您不必修改所有现有源,而只需添加新文件。使用您的构建系统选择适当的源文件。

Example structure:

示例结构:

include/probe.h
src/arch/win32/probe.cpp
src/arch/linux/probe.cpp
src/arch/mac/probe.cpp

The warning is because probe() doesn't return a value. In other words, none of the three #ifdefs matches.

警告是因为 probe() 不返回值。换句话说,三个#ifdef 都不匹配。

回答by ereOn

It seems none of TARGET_OS_MAC, __linux__, _WIN32or _WIN64is defined at the time you compile your code.

似乎没有一个TARGET_OS_MAC__linux___WIN32或者_WIN64在您编译代码的时间定义。

So its like your code was:

所以它就像你的代码是:

bool probe(){
}

That's why the compiler complains about reaching the end of a non-void function. There is no returnclause.

这就是编译器抱怨到达非空函数末尾的原因。没有return条款。



Also, for the more general question, here are my guidelines when developping multi-platform/architecure software/libraries:

此外,对于更一般的问题,以下是我在开发多平台/架构软件/库时的指导方针:

Avoid specific cases. Try to write code that is OS-agnostic.

避免特定情况。尝试编写与操作系统无关的代码。

When dealing with system specific stuff, try to wrap things into "opaque" classes. As an example, if you are dealing with files (different APIs on Linux and Windows), try to create a Fileclass that will embed all the logic and provide a common interface, whatever the operating system. If some feature is not available on one of the OS, deal with it: if the feature makes no sense for a specific OS, it's often fine to do nothing at all.

在处理系统特定的东西时,尝试将东西包装到“不透明”类中。例如,如果您正在处理文件(Linux 和 Windows 上的不同 API),请尝试创建一个File类,该类将嵌入所有逻辑并提供通用接口,无论操作系统如何。如果某个功能在某个操作系统上不可用,请处理它:如果该功能对特定操作系统没有意义,通常什么都不做也可以。

In short: the less #ifdefthe better. And no matter how portable your code is, test it on every platform before releasing it.

简而言之:#ifdef越少越好。而且无论您的代码有多便携,在发布之前都要在每个平台上进行测试。

Good luck ;)

祝你好运 ;)

回答by Tristan

The warning is because if none of the defines are actually defined then you have no returnin your probe function. The fix for that is put in a default return.

警告是因为如果实际上没有定义任何定义,那么您return的探测函数中就没有。对此的修复放在默认的return.

回答by Lee Hambley

To add something more to this, other than the outstanding options above, the directives __linux__and _WIN32are known to the compiler, where the TARGET_OS_MACdirective was not, this can be resolved by using __APPLE__. Source: http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html

要为此添加更多内容,除了上述未完成的选项之外,指令__linux___WIN32编译器已知,如果TARGET_OS_MAC指令不知道,则可以使用__APPLE__. 资料来源:http: //www.winehq.org/pipermail/wine-patches/2003-July/006906.html