16

我正在制作一个 C++ 程序。

我对 C++ 最大的烦恼之一是它所谓的平台独立性。

大家可能都知道,在没有大量神秘错误和特定于平台的包含文件的情况下,在 Windows 中编译 Linux C++ 程序和在 Linux 中编译 Windows 程序几乎是不可能的。

当然你总是可以切换到像 Cygwin 和 wine 这样的仿真,但我问你,真的没有别的办法吗?

4

9 回答 9

37

该语言本身是跨平台的,但大多数库不是,但是如果您想在使用 C++ 编程时完全跨平台,则应牢记三件事。

首先,您需要开始使用某种跨平台构建系统,例如SCons。其次,您需要确保您使用的所有库都是跨平台的。第三点,我建议使用所有目标平台上都存在的编译器,这里要考虑gcc(C++ 是一个相当复杂的野兽,所有编译器都有自己的特定怪癖)。

我有一些关于图形用户界面的进一步建议给你。其中有几种可供使用,最值得注意的三个是:

GTK+QT是两个 API,它们带有自己的小部件集(按钮、列表等),而wxWidgets更像是当前运行平台本机小部件集的包装 API。这意味着与系统的其他部分相比,前者看起来可能有点不同,而后者看起来就像一个原生程序。

如果你喜欢游戏编程,那么有同样多的 API 可供选择,而且它们都是跨平台的。我所知道的两个最全面的功能是:

两者都包含从图形到输入和音频例程的所有内容,无论是通过插件还是内置的。

此外,如果您觉得 C++ 中的标准库有点缺乏,请查看Boost以获得一些通用的跨平台甜头。

祝你好运。

于 2009-01-25T21:18:29.400 回答
13

C++ 是跨平台的。您似乎遇到的问题是您正在使用平台相关库。

我假设你真的在谈论 UI 组件——在这种情况下,我建议使用 GTK+、Qt 或 wxWindows 之类的东西——每个都有可以为不同系统编译的 UI 组件。

唯一的解决方案是让您找到和使用与平台无关的库。

而且,顺便说一句,cygwin 和 Wine 都不是仿真的——它们是在各自系统中找到的相同功能的 100% 本机实现。

于 2009-01-25T21:19:55.203 回答
9

一旦你意识到了陷阱,它实际上并不难。我目前正在编写的所有代码都在 32 位和 64 位 Windows、各种Linux以及 Unix(Sun、HP 和 IBM)上编译。显然,这些不是 GUI 产品。此外,我们不使用第三方库,除非我们自己编译它们。

我有一个 .h 文件,其中包含所有特定于编译器的代码。例如,Microsoft 和 gcc 在如何指定 8 位整数上存在分歧。所以在.h中,我有

#if defined(_MSC_VER)
   typedef __int8 int8_t;
 #elif defined(__unix)
   typedef char int8_t;
 #endif

还有相当多的代码统一了某些较低级别的函数调用,例如:

#if defined(_MSC_VER)
  #define SplitPath(Path__,Drive__,Name__,Ext__) _splitpath(Path__,Drive__,Dir__,Name__,Ext__)
#elif defined(__unix)
  #define SplitPath(Path__,Drive__,Name__,Ext__) UnixSplitPath(Path__,Drive__,Name__,Ext__)
#endif

现在在这种情况下,我相信我必须编写一个 UnixSplitPath() 函数——有时你需要。但大多数时候,您只需要找到正确的替换函数即可。在我的代码中,我将调用 SplitPath(),即使它在任一平台上都不是本机函数;#defines 会帮我解决。训练自己需要一段时间。

信不信由你,我的 .h 文件只有 240 行长。真的没什么。这包括处理字节序问题。

一些较低级别的东西将需要条件编译。例如,在 Windows 中,我使用临界区,但在 Linux 中,我需要使用 pthread_mutex。CriticalSection 被封装在一个类中,这个类有很多条件编译。但是,上层程序完全不知道,无论平台如何,类的功能都完全相同。

我可以告诉你的另一个秘密是:经常在所有平台上构建你的项目(尤其是在开始时)。当您将编译器问题扼杀在萌芽状态时,这会容易得多。不要等到完成开发后再尝试跨平台。

于 2009-01-26T15:11:44.663 回答
2

坚持使用跨平台的 ANSI C++ 和库,你应该没问题。

于 2009-01-25T22:31:11.750 回答
1

创建一些包含项目中所有特定于平台的代码的低级层。实现这一层的 2 个版本——一个用于 Windows,一个用于 Linux——具有相同的接口,并将它们构建为 2 个库。通过该界面访问项目中所有特定于平台的功能。

该层可以包含用于文件访问、打印、GUI 等的通用类。

使用该层的所有(现在非平台特定的)代码现在可以在 Windows 上编译一次,在 Linux 上编译一次。

于 2009-01-25T21:30:31.017 回答
0

在 Window 中编译它,然后在 Linux 中再次编译。除非您使用特定于平台的库,否则它应该可以工作。它不像Java,你编译一次就可以在任何地方工作。没有人为 C++ 制作过虚拟机,而且可能永远也不会。您用 C++ 编写的代码可以在任何平台上运行。你只需要先在每个平台上编译它。

于 2009-01-25T21:18:25.970 回答
0

建议:

  • 对整数使用 typedef。或#include <stdint.h>。有些机器认为 int 是 8 个字节,有些是 4 个。(以前是 2 和 4。时代怎么变了。)

  • 尽可能使用封装。我最后一个窗口的编译器认为 %lld 是 %I64d",给出了 vsnprintf() 的错误返回值,close() 和套接字的类似问题等。

  • 注意堆栈大小/缓冲区大小限制。我在 Windows 下遇到了 8k UDP 缓冲区限制,以及其他问题。

  • 出于某种原因,我的 Window 的 C++ 编译器不接受堆栈外的动态大小分配。例如: void foo(int a) { int b[a]; 注意这些事情。计划如何重新编码。

  • #ifdef 可以成为你最好的朋友。还有你最大的敌人!(同时!)

当然可以。但是要尽早并经常编译和测试!

于 2009-01-26T09:07:36.567 回答
0

Linux 和 Windows 也有不同的数据模型。见文章:64 位程序开发中被遗忘的问题

于 2009-01-26T14:52:04.610 回答
-1

标准 C++是在任何平台上都可以无错误编译的代码。尝试在 Windows 上使用Bloodshed Dev C++(而不是 VC++/Borland C++)。

由于 Bloodshed Dev C++ 确认了 C++ 标准,因此使用它编译的程序将在大多数情况下在 linux 上编译而不会出错。

于 2009-01-26T09:09:26.987 回答