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

时间:2022-06-04 03:00:58

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 apps交互(好的,这部分稍后会讲到…)

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:在函数“bool探测器()”:untitled:29:警告:控制达到非void函数的结束,但我也真的很感激任何信息或资源的人可以建议如何编写这样的代码更好....

5 个解决方案

#1


32  

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链,可以消除错误,因为如果没有有效的返回语句或命中#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/3PArXCxo for a sample error message. You can use the special preprocessing-only defined operator, 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或build系统)。事实上,这是使用模板和内联函数的最实用的解决方案,这使得它比试图消除预处理器更灵活。它与整个文件方法结合得很好,因此您仍然可以在适当的时候使用它。

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,以定义该宏(记住,对宏名使用前缀)。

#2


46  

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()不返回值。换句话说,这三种方法都不匹配。

#3


5  

It seems none of TARGET_OS_MAC, __linux__, _WIN32 or _WIN64 is 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 return clause.

这就是为什么编译器会抱怨到非void函数的末尾。没有退货条款。


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 File class 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),请尝试创建一个文件类,它将嵌入所有逻辑并提供一个公共接口,无论操作系统是什么。如果某个操作系统上没有可用的特性,请处理它:如果该特性对特定的操作系统没有意义,那么最好什么都不做。

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

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

Good luck ;)

祝你好运,)

#4


1  

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

警告是,如果没有定义,那么在探针函数中就没有返回。对此的修正将放在默认返回中。

#5


1  

To add something more to this, other than the outstanding options above, the directives __linux__ and _WIN32 are known to the compiler, where the TARGET_OS_MAC directive 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

#1


32  

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链,可以消除错误,因为如果没有有效的返回语句或命中#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/3PArXCxo for a sample error message. You can use the special preprocessing-only defined operator, 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或build系统)。事实上,这是使用模板和内联函数的最实用的解决方案,这使得它比试图消除预处理器更灵活。它与整个文件方法结合得很好,因此您仍然可以在适当的时候使用它。

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,以定义该宏(记住,对宏名使用前缀)。

#2


46  

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()不返回值。换句话说,这三种方法都不匹配。

#3


5  

It seems none of TARGET_OS_MAC, __linux__, _WIN32 or _WIN64 is 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 return clause.

这就是为什么编译器会抱怨到非void函数的末尾。没有退货条款。


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 File class 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),请尝试创建一个文件类,它将嵌入所有逻辑并提供一个公共接口,无论操作系统是什么。如果某个操作系统上没有可用的特性,请处理它:如果该特性对特定的操作系统没有意义,那么最好什么都不做。

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

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

Good luck ;)

祝你好运,)

#4


1  

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

警告是,如果没有定义,那么在探针函数中就没有返回。对此的修正将放在默认返回中。

#5


1  

To add something more to this, other than the outstanding options above, the directives __linux__ and _WIN32 are known to the compiler, where the TARGET_OS_MAC directive 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