C++ 应用程序是跨平台的吗?
Are C++ applications cross-platform?
作为一名学生,我学到的第一件事就是 C++ 应用程序不会 运行 在不同的操作系统上。最近,我到处都看到基于 Qt 的 C++ 应用程序 运行。那么发生了什么? C++ 应用程序是否跨平台?
标准 C++ 是 "write once, compile anywhere" 意义上的跨平台,但不是 "compile once, run anywhere" 意义上的跨平台。
这意味着如果您使用标准 C++ 编写程序,则可以在具有符合标准的 C++ 实现的任何目标环境中编译然后运行它。
但是,您不能在您的机器上编译您的程序,发送二进制文件,然后期望它在其他目标上运行。 (至少不是一般情况。当然可以在某些条件下从 C++ 代码分发二进制文件,但这取决于实际目标。这是一个广泛的领域。)
当然,如果您使用额外的非标准功能,例如 gcc 的可变长度数组或第三方库,您只能在提供这些扩展和库的系统上进行编译。
Qt 和 Boost 等一些库在许多系统上都可用(我相信至少在 Linux、Mac 和 Windows 上有这两个库),因此您的代码将保持跨平台如果你使用这些。
是的。不,也许吧。什么是 cross-platform C++ 代码? Cross-platformC++代码就是这样一种代码,可以在不同的操作系统下编译而无需修改。
这意味着,如果您显式使用任何 platform-dependant headers,您的代码将不再是 cross-platform。 Qt 通过以下方式解决了这个问题:它们为 platform-specific 中的所有内容提供了包装器。例如,假设您正在使用 QFile
到 open/read/write 一个文件。你的代码看起来像
QFile file(filename);
file.open(QFile::ReadOnly);
//other stuff
您可以在任何 OS 下编译此代码,只要您有适合该 OS 的编译器和 Qt 库。隐藏在 QFile
下的代码将使用 OS-appropriate file-handling 函数,但这与您无关。
此外,如果您只使用标准库,则可以在任何有 C++ 编译器的地方编译您的代码。
但是,already-compiled 应用程序 cross-platform 不同于 Java 应用程序 - 例如,您无法为 Windows 然后 运行 在 Linux 中,您将不得不在 Linux 下重新编译您的代码。
源代码兼容。如果我编译源码,会不会到处都是运行?
API/ABI 兼容性。 OS 是否以代码可以理解的方式为其组件提供接口?
二进制兼容性。代码是否能够在目标主机上 运行ning?
源代码兼容
C++
是定义结构、内存、文件如何读写的标准。
#include <iostream>
int main( int argc, char ** argv )
{
std::cout << "Hello World" << std::endl;
}
为处理数据而编写的代码(例如grep
、awk
、sed
)通常是跨平台的。
当你想与用户交互时,现代操作系统有一个 GUI,这些都不是跨平台的,会导致为特定平台编写代码。
qt
或 wxWidgets
等库具有针对多个平台的实现,并允许您针对 qt
而不是 Windows
或 iOS
进行编程,其中结果与两者兼容。
这些匿名化 库的问题在于,为了跨平台的一致性,它们剥夺了平台 X 的一些特定优势。
这方面的示例是在 Windows
上使用 WaitForMultipleObjects
函数,它允许您等待不同类型的事件发生,或者在 UNIX 上使用 fork
函数,它允许您的进程的两个副本成为 运行 重要的共享状态。在 UI 中,表单的外观和行为略有不同(例如颜色选择器、最大化、最小化、在 window 之外跟踪鼠标的能力、手势行为)。
当您需要完成的工作对您很重要时,您可能最终想要编写特定于平台的代码以利用特定应用程序的优势。
C
库 sqlite
是广泛的跨平台代码,但其低级 IO 是平台特定的,因此它可以保证数据库完整性(数据确实写入到磁盘)。
所以 Qt 等库确实可以工作,但它们可能会产生不令人满意的结果,最终您不得不编写本机代码。
API/ABI兼容性
不同版本的 UNIX 和 Windows 具有某种形式的相互兼容性。这些允许为 OS 的一个版本构建的二进制文件到 OS.
的其他版本上的 运行
在 UNIX 中,构建机器的选择决定了兼容性。您希望支持的最低 OS 修订应该是您的构建机器,它将生成与后续次要版本兼容的二进制文件,直到它们做出重大更改(弃用库)。
在 Windows 和 Mac OS X 上,您选择一个 SDK,它允许您针对一组 OS 具有与重大更改相同的问题.
在 Linux,每个内核修订版都与任何其他内核修订版 ABI 不兼容,并且需要为每个内核修订版重新编译内核模块。
二进制兼容性
这是CPU理解代码的能力。这比您想象的要复杂,因为 x64 芯片能够(取决于 OS 支持)运行ning x86 代码。
通常情况下,C++ 程序被打包在一个容器(PE 可执行文件,ELF 格式)中,操作系统使用该容器解压缩代码和数据部分并加载库。这使得最终程序具有二进制(代码类型)和 API(容器格式)形式的不兼容性。
同样在今天,如果您编译 x86 Windows 应用程序(针对 Windows 7 on Visual Studio 2015),那么如果处理器没有 SSE2 指令,代码可能无法执行(10岁左右CPU).
最终,当 Apple 从 PowerPC 更改为 x86 时,他们提供了一个仿真层,允许旧的 PowerPC 代码在 x86 平台上的仿真器中运行。
所以一般来说二进制不兼容是一个模糊的区域。可以生成一个 OS 来识别无效指令(例如 SSE2)并在故障中模拟行为,这可以随着新功能的出现而更新,并使您的代码保持 运行ning,即使它是二进制不兼容的。
即使您的平台无法运行设置某种形式的指令集,它也可以被模拟并表现得兼容。
C++ 是跨平台的。您可以使用它构建可在许多不同操作系统上 运行 的应用程序。
不是跨平台的是将 C++ 翻译成目标代码的编译器。据我所知,没有一个编译器具有所有必要的功能,因此当您使用它编译 C++ 程序时,它会自动 运行 on Windows、Linux 和 Mac OS.
Qt Creator 与多个编译器集成并具有构建自动化功能。它可以轻松地在不同的设置和目标平台之间切换。它为构建、运行宁和部署 C++ 应用程序提供支持,不仅适用于桌面环境,也适用于移动设备。
您可以实现您的源代码在各种平台上编译,为您提供来自同一源代码库的各种二进制文件。
这不是 "compile once, run anywhere with an appropriate VM" Java 或 C# 做的,而是 "write once, compile anywhere with an appropriate environment" C 一直做的方式。
由于标准库不提供您可能需要的一切,您必须寻找第三方库来提供该功能。某些框架——如 Boost、Qt、GTK+、wxWidgets 等——可以提供这一点。由于这些框架 是 以它们在不同平台上 编译 的方式编写的,因此您可以实现上述意义上的跨平台功能。
如果您希望您的 C++ 代码是跨平台的,则需要注意各种事项。
显而易见的是对数据类型做出假设的来源。您的 long
可能是这里的 32 位和那里的 64 位。数据类型对齐和结构填充可能不同。这里有 "play it safe" 的方法,如 size_t
/ size_type
/ uint16_t
typedefs 等,也有错误的方法,如 wchar_t
和 std::wstring
. "get it right".
需要纪律和一些经验
并非所有编译器生而平等。如果您需要源代码在其他平台上编译,则不能使用所有最新的 C++ 语言功能,或使用依赖于这些功能的库C++ 编译器。先检查compatibility chart。
另一件事是endianess。仅举一个例子,当您在一个平台(例如 x86 或 x86_64)上将整数流写入文件,然后在另一个平台(例如 POWER)上再次读回它时,您可以 运行 成问题。为什么要将整数写入文件?好吧,UTF-16 是 整数...同样,纪律和一些经验对使这相当轻松。
选中所有那些框后,您需要确保 库的可用性 您的代码基于.虽然 std::
是安全的(但请参阅上面的 "not all compilers are created equal"),但如果您超越主流,像 boost::
这样无辜的东西可能会成为问题。 (在过去的几年里,我帮助 Boost 人员修复了一两个关于 AIX / Visual Age 的问题,仅仅是因为他们无法访问该平台来测试新版本...)
哦,注意那里的各种 许可方案 。一些提高跨平台能力的框架——比如 Qt 或 Cygwin——有它们的附加条件。这并不是说它们在适当的情况下没有太大帮助,只是您需要了解 copyleft/专有许可要求。
综上所述,还有 Wine ("Wine is not emulation"),这使得 compiled for Windows 运行 在各种类 Unix 系统上(Linux、OS X、*BSD、Solaris)。它的功能有一定的局限性,但它一直在变得更好。
C++ 是一种编程语言。文本。因此,它不会 运行 任何地方。
符合标准的 C++ 代码应在任何平台上表现; "cross-platform" 如果你愿意的话。编写(严格)符合 C++ 的代码需要迂腐,因为通常做出的一些假设依赖于最终实现的细节,而这继承自 C++ 本身的目标。
请注意,我们仍在谈论 C++ 代码,而不是 C++ 程序。事实上,当我们传递到术语 "program" 时,我们不再有任何保证,因为我们不再谈论 C++;相反,编译器的输出。这就是可移植性开始消失的地方:可执行格式、ISA、ABI、低级例程等等。
你能相信吗?如果不能,则需要将 C++ 程序集成到它将 运行 运行的环境中,方法是重新编译它或使用特定于平台的元素。
作为一名学生,我学到的第一件事就是 C++ 应用程序不会 运行 在不同的操作系统上。最近,我到处都看到基于 Qt 的 C++ 应用程序 运行。那么发生了什么? C++ 应用程序是否跨平台?
标准 C++ 是 "write once, compile anywhere" 意义上的跨平台,但不是 "compile once, run anywhere" 意义上的跨平台。
这意味着如果您使用标准 C++ 编写程序,则可以在具有符合标准的 C++ 实现的任何目标环境中编译然后运行它。
但是,您不能在您的机器上编译您的程序,发送二进制文件,然后期望它在其他目标上运行。 (至少不是一般情况。当然可以在某些条件下从 C++ 代码分发二进制文件,但这取决于实际目标。这是一个广泛的领域。)
当然,如果您使用额外的非标准功能,例如 gcc 的可变长度数组或第三方库,您只能在提供这些扩展和库的系统上进行编译。
Qt 和 Boost 等一些库在许多系统上都可用(我相信至少在 Linux、Mac 和 Windows 上有这两个库),因此您的代码将保持跨平台如果你使用这些。
是的。不,也许吧。什么是 cross-platform C++ 代码? Cross-platformC++代码就是这样一种代码,可以在不同的操作系统下编译而无需修改。
这意味着,如果您显式使用任何 platform-dependant headers,您的代码将不再是 cross-platform。 Qt 通过以下方式解决了这个问题:它们为 platform-specific 中的所有内容提供了包装器。例如,假设您正在使用 QFile
到 open/read/write 一个文件。你的代码看起来像
QFile file(filename);
file.open(QFile::ReadOnly);
//other stuff
您可以在任何 OS 下编译此代码,只要您有适合该 OS 的编译器和 Qt 库。隐藏在 QFile
下的代码将使用 OS-appropriate file-handling 函数,但这与您无关。
此外,如果您只使用标准库,则可以在任何有 C++ 编译器的地方编译您的代码。
但是,already-compiled 应用程序 cross-platform 不同于 Java 应用程序 - 例如,您无法为 Windows 然后 运行 在 Linux 中,您将不得不在 Linux 下重新编译您的代码。
源代码兼容。如果我编译源码,会不会到处都是运行?
API/ABI 兼容性。 OS 是否以代码可以理解的方式为其组件提供接口?
二进制兼容性。代码是否能够在目标主机上 运行ning?
源代码兼容
C++
是定义结构、内存、文件如何读写的标准。
#include <iostream>
int main( int argc, char ** argv )
{
std::cout << "Hello World" << std::endl;
}
为处理数据而编写的代码(例如grep
、awk
、sed
)通常是跨平台的。
当你想与用户交互时,现代操作系统有一个 GUI,这些都不是跨平台的,会导致为特定平台编写代码。
qt
或 wxWidgets
等库具有针对多个平台的实现,并允许您针对 qt
而不是 Windows
或 iOS
进行编程,其中结果与两者兼容。
这些匿名化 库的问题在于,为了跨平台的一致性,它们剥夺了平台 X 的一些特定优势。
这方面的示例是在 Windows
上使用 WaitForMultipleObjects
函数,它允许您等待不同类型的事件发生,或者在 UNIX 上使用 fork
函数,它允许您的进程的两个副本成为 运行 重要的共享状态。在 UI 中,表单的外观和行为略有不同(例如颜色选择器、最大化、最小化、在 window 之外跟踪鼠标的能力、手势行为)。
当您需要完成的工作对您很重要时,您可能最终想要编写特定于平台的代码以利用特定应用程序的优势。
C
库 sqlite
是广泛的跨平台代码,但其低级 IO 是平台特定的,因此它可以保证数据库完整性(数据确实写入到磁盘)。
所以 Qt 等库确实可以工作,但它们可能会产生不令人满意的结果,最终您不得不编写本机代码。
API/ABI兼容性
不同版本的 UNIX 和 Windows 具有某种形式的相互兼容性。这些允许为 OS 的一个版本构建的二进制文件到 OS.
的其他版本上的 运行在 UNIX 中,构建机器的选择决定了兼容性。您希望支持的最低 OS 修订应该是您的构建机器,它将生成与后续次要版本兼容的二进制文件,直到它们做出重大更改(弃用库)。
在 Windows 和 Mac OS X 上,您选择一个 SDK,它允许您针对一组 OS 具有与重大更改相同的问题.
在 Linux,每个内核修订版都与任何其他内核修订版 ABI 不兼容,并且需要为每个内核修订版重新编译内核模块。
二进制兼容性
这是CPU理解代码的能力。这比您想象的要复杂,因为 x64 芯片能够(取决于 OS 支持)运行ning x86 代码。
通常情况下,C++ 程序被打包在一个容器(PE 可执行文件,ELF 格式)中,操作系统使用该容器解压缩代码和数据部分并加载库。这使得最终程序具有二进制(代码类型)和 API(容器格式)形式的不兼容性。
同样在今天,如果您编译 x86 Windows 应用程序(针对 Windows 7 on Visual Studio 2015),那么如果处理器没有 SSE2 指令,代码可能无法执行(10岁左右CPU).
最终,当 Apple 从 PowerPC 更改为 x86 时,他们提供了一个仿真层,允许旧的 PowerPC 代码在 x86 平台上的仿真器中运行。
所以一般来说二进制不兼容是一个模糊的区域。可以生成一个 OS 来识别无效指令(例如 SSE2)并在故障中模拟行为,这可以随着新功能的出现而更新,并使您的代码保持 运行ning,即使它是二进制不兼容的。
即使您的平台无法运行设置某种形式的指令集,它也可以被模拟并表现得兼容。
C++ 是跨平台的。您可以使用它构建可在许多不同操作系统上 运行 的应用程序。
不是跨平台的是将 C++ 翻译成目标代码的编译器。据我所知,没有一个编译器具有所有必要的功能,因此当您使用它编译 C++ 程序时,它会自动 运行 on Windows、Linux 和 Mac OS.
Qt Creator 与多个编译器集成并具有构建自动化功能。它可以轻松地在不同的设置和目标平台之间切换。它为构建、运行宁和部署 C++ 应用程序提供支持,不仅适用于桌面环境,也适用于移动设备。
您可以实现您的源代码在各种平台上编译,为您提供来自同一源代码库的各种二进制文件。
这不是 "compile once, run anywhere with an appropriate VM" Java 或 C# 做的,而是 "write once, compile anywhere with an appropriate environment" C 一直做的方式。
由于标准库不提供您可能需要的一切,您必须寻找第三方库来提供该功能。某些框架——如 Boost、Qt、GTK+、wxWidgets 等——可以提供这一点。由于这些框架 是 以它们在不同平台上 编译 的方式编写的,因此您可以实现上述意义上的跨平台功能。
如果您希望您的 C++ 代码是跨平台的,则需要注意各种事项。
显而易见的是对数据类型做出假设的来源。您的 long
可能是这里的 32 位和那里的 64 位。数据类型对齐和结构填充可能不同。这里有 "play it safe" 的方法,如 size_t
/ size_type
/ uint16_t
typedefs 等,也有错误的方法,如 wchar_t
和 std::wstring
. "get it right".
并非所有编译器生而平等。如果您需要源代码在其他平台上编译,则不能使用所有最新的 C++ 语言功能,或使用依赖于这些功能的库C++ 编译器。先检查compatibility chart。
另一件事是endianess。仅举一个例子,当您在一个平台(例如 x86 或 x86_64)上将整数流写入文件,然后在另一个平台(例如 POWER)上再次读回它时,您可以 运行 成问题。为什么要将整数写入文件?好吧,UTF-16 是 整数...同样,纪律和一些经验对使这相当轻松。
选中所有那些框后,您需要确保 库的可用性 您的代码基于.虽然 std::
是安全的(但请参阅上面的 "not all compilers are created equal"),但如果您超越主流,像 boost::
这样无辜的东西可能会成为问题。 (在过去的几年里,我帮助 Boost 人员修复了一两个关于 AIX / Visual Age 的问题,仅仅是因为他们无法访问该平台来测试新版本...)
哦,注意那里的各种 许可方案 。一些提高跨平台能力的框架——比如 Qt 或 Cygwin——有它们的附加条件。这并不是说它们在适当的情况下没有太大帮助,只是您需要了解 copyleft/专有许可要求。
综上所述,还有 Wine ("Wine is not emulation"),这使得 compiled for Windows 运行 在各种类 Unix 系统上(Linux、OS X、*BSD、Solaris)。它的功能有一定的局限性,但它一直在变得更好。
C++ 是一种编程语言。文本。因此,它不会 运行 任何地方。
符合标准的 C++ 代码应在任何平台上表现; "cross-platform" 如果你愿意的话。编写(严格)符合 C++ 的代码需要迂腐,因为通常做出的一些假设依赖于最终实现的细节,而这继承自 C++ 本身的目标。
请注意,我们仍在谈论 C++ 代码,而不是 C++ 程序。事实上,当我们传递到术语 "program" 时,我们不再有任何保证,因为我们不再谈论 C++;相反,编译器的输出。这就是可移植性开始消失的地方:可执行格式、ISA、ABI、低级例程等等。
你能相信吗?如果不能,则需要将 C++ 程序集成到它将 运行 运行的环境中,方法是重新编译它或使用特定于平台的元素。