如何编写跨平台程序?

6

我搜索了一些关于跨平台编程开发的文献,但并没有找到非常好的内容。

我不是在寻找像Java那样的虚拟机进行跨平台开发。

是否有任何关于此方面的书籍或文献?


2
你如何定义跨平台?例如, ANSI C 程序可以在许多平台上编译。 - James Black
3
你的程序需要哪些特性?你想要支持哪些平台?如果依赖于 POSIX 规范中指定的特性,你的程序将能够在许多 Unix 系统上移植,但可能无法编译运行在 Windows 平台上 - 除非你依赖于 Windows 支持的 POSIX 子集。另一种使程序具备可移植性的方法是依赖于一个抽象层,处理平台特定的事情,例如 Qt 的网络和线程设施。采用这种方法的问题在于,你的程序最多只能在支持你的抽象层的系统上移植使用。 - George
例如,一个使用套接字的程序。它在Linux或Windows中有不同的实现。 - rigon
3
"套接字不是一个好的例子。套接字 API 在 UNIX 和 Windows 上几乎都使用 Berkley 套接字标准化了。" - Eric Petroelje
如此多的问题:不仅include有所不同,还有其他细节,例如参数类型等。您可以通过使用ifdef或使用高级库来解决这个问题。如果您使用C++,例如可以使用Boost.Asio(http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio.html)。 - Staffan
显示剩余3条评论
7个回答

7
我认为这可以归结为以下几点:
- 不使用非标准的“标准库”功能,其中非标准取决于您所针对的平台(例如,符合POSIX标准的系统)。例如,如果您使用C语言,则不要在非POSIX系统上运行应用程序时使用popen()。 - 确保在需要处理端序的情况下正确处理,例如在向另一台可能使用不同字节顺序的计算机传输数据时。 - 仅编写符合规范的代码,例如不依赖于GCC / VC /命名您的编译器特定功能。
更实际的建议是:
- 使用跨平台库来抽象您所需的非标准功能,或编写能够处理您所针对的所有平台的代码。 - 同时,避免非跨平台依赖项。例如,使用OpenGL而不是Direct3D,使用Qt / Gtk /任何其他跨平台工具包而不是您平台本地的小部件工具包。
编辑:还有更多需要考虑的问题,例如不假设/用作路径分隔符,或对文件名中允许使用哪些字符进行无效的假设。

5

@Staffan和其他人提供了宝贵的建议,因此我不会提供解决方案 - 只是建议一种方法。

有很多可能的解决方案,我认为一个重要的决定是是否需要GUI。如果不需要,则可以使用C语言。而对于GUI,可以使用Java(你不想用),或者使用NetBEans作为IDE,并使用Qt作为小部件。

但无论你做什么,我认为最重要的是尽早检测潜在问题。如果你使用C语言,可以使用Splint或其他静态代码分析工具来警告可移植性问题。同样地,将编译器警告级别设置为最高应该会有所帮助。

设置连续集成系统(如Hudson)以定期构建所有内容,并确保拥有大量的自动化单元测试(使用CppUnit或类似工具),并在每个平台上使用相同的测试,针对可移植性问题进行测试。

也许可以考虑Posix或仅使用Ansi C或其他符合标准的语言。

如何设置CI取决于您有多少潜在目标。也许您需要在单独的PC或VM上运行每个目标。如果您选择C或C ++,则可能希望在Windows下使用Cygwin中的GCC以及您选择的C / C ++编译器(需要建议好的免费编译器?)
另请参阅:

http://www.hookatooka.com/wpc/

当然,还有http://www.google.com/search?hl=en&rls=com.microsoft%3Aen-sg&q=portable+code等相关内容。


将近十年过去了,我推荐使用Flutter。你试过吗?我想现在的平台已经与十年前不同了 :-) - Mawg says reinstate Monica

3

我曾经向别人要一本书,但是没有人推荐给我。

我发现了一本名为“C++跨平台开发:构建Mac OS X、Linux和Windows应用程序”的书。

这里有一个亚马逊的链接和对于感兴趣的人的描述:

http://www.amazon.com/exec/obidos/tg/detail/-/032124642X/

   C++跨平台开发是开发可在Windows、Macintosh和Linux/Unix平台上本地运行而不会影响功能、易用性或质量的可移植C/C++应用程序代码的权威指南。
长期从事Mozilla和Netscape开发的Syd Logan系统地解决了与软件可移植性相关的所有技术和管理挑战,从规划和设计到编码、测试和部署。Logan凭借其丰富的跨平台开发经验,全面介绍了从使用本机API到最新的可移植GUI开发策略等问题。在此过程中,他演示了如何实现特性平衡,同时避免传统跨平台开发方法固有的问题。
这本书将成为每个正在构建新的跨平台软件、移植现有C/C++软件或计划可能需要跨平台支持的软件的软件专业人员和技术经理的必备资源。
不折衷地构建跨平台应用程序
在整本书中,Logan通过现实场景和大量可下载的代码示例阐明了他的技巧,包括一个基于Mozilla XUL的完整跨平台GUI工具包,您可以下载、修改和学习。覆盖范围包括: - Netscape使用的策略和程序,使他们能够在Windows、Mac OS和Linux上向数百万用户提供Web浏览器 - 提供在所有平台上一致的功能和界面 - 了解领先的特定于平台的GUI API之间的关键相似性和差异,包括Win32/.NET、Cocoa和Gtk+ - 确定何时使用本机IDE,何时不使用以及如何限制其对可移植性的影响 - 利用基于标准的API,包括POSIX和STL - 避免与C++中的浮点、字符类型、数据序列化和类型相关的隐藏可移植性陷阱 - 利用平台抽象库,如Netscape可移植运行时(NSPR) - 建立有效的跨平台错误报告和跟踪系统 - 为多个平台创建构建并在平台发生构建失败时检测它们 - 了解本机运行时环境及其对安装的影响 - 利用wxWidgets从单个代码库创建多平台GUI应用程序 - 充分测试应用程序的可移植性 - 了解使用Trixul进行跨平台GUI工具包设计

2
如果您没有使用“一次编码,多处运行”的开发环境(换句话说,您的某些代码必须为每个目标平台进行定制),那么请确保您真的需要您的程序在多个平台上运行。
我知道一个程序可以编译成两个版本,一个用于Mac,一个用于Windows。尽管两个平台的大部分代码相同,但其中一部分是特定于主机操作系统的,并且经常需要针对这两个环境进行修改和测试。销售额为98%的Windows,2%的Mac,然而两个版本基本上需要相等的设计/编程/测试/文档编写时间。所有者决定,与其将未来程序员时间的一半给予只有2%回报率的Mac版本,他们干脆放弃了该版本。他们的跨平台问题立即消失了,程序员的生产力基本翻了一倍(这让Windows客户感到满意)。

1

如果不使用虚拟机,你总会遇到同样的问题:很多操作系统可以使用的特性都是特定于该操作系统的。

这是因为没有人真正关心定义完成相同任务的方法,主要因为例如拥有DirectX10等功能对其他操作系统来说是一个优势。

我认为编写跨平台应用程序非常容易,在MacosX和Linux上运行,因为你可以利用许多能够在两台机器上运行的东西(考虑X11或GTK),它们都在Unix下运行。通常,只要付出一些努力,你就可以使你的程序在Windows下工作(也许使用MinGW或Cygwin),即使某些功能的兼容性缺失。

此外,不同的操作系统对于同样的事物实际上具有不同的实现方式(如套接字、io系统、图形、音频等),所以这使得仅编写一个在任何地方均可工作的版本成为不可能:你必须为计划发布程序的每个操作系统编写不同的版本。

简短的答案是:除非你限制你的程序功能到一小组共同的特性,否则你不能没有虚拟机语言。

(我假设我们正在谈论C/C++,因为通常其他语言由各自的人组成的一个小组来管理,他们尽可能地进行跨平台发布)

我并没有真正看到在依赖虚拟机方面存在任何明显的缺点。如今的计算机可以在不影响速度的情况下运行虚拟机。因此,有一些关注于在您和操作系统之间放置抽象层的东西,将让您只需掌握一种方法就能做一些高级的事情。我认为像Java这样的速度妥协是被广泛接受的……他们只是在尝试编写一个复杂的跨平台应用程序时所必须做的。

仅仅是个事实:当我尝试将我编写的虚拟机从Unix(Linux / OSX)移植到Windows时,我遇到了很多痛苦,因为freopen函数存在问题……不幸的是,相对于其他操作系统,Windows以不同的方式管理流,因此MinGW缺少了该功能,而我不得不找到解决该问题的方法。


1
@Jack - 这并不完全正确。在C或C++中使用条件编译,您可以编写一个程序,在每个平台上都使用特定于操作系统的功能,并以不同的方式进行编译。当然,在这种情况下,付出的努力几乎与编写两个应用程序相同。 - Eric Petroelje
3
是的,但这并不是编写跨平台应用程序。这是编写两个不同的应用程序,依赖于一些共享(跨平台)组件,这些组件不使用高级功能。条件编译是一种在许多平台上编译而不需要真正的跨平台程序的方法(因为正如您也所述,这种工作量几乎与编写两个应用程序相当)。 - Jack
有许多开源程序可以在Windows和各种Unix操作系统上编译,例如,通过使用autoconf,您可以使环境适应以便在几乎任何操作系统/硬件组合上进行编译。 - James Black
@Jack:你似乎不知道或选择忽略tcl/tk和python/wxPython等语言和工具包,它们在抽象化操作系统和窗口系统方面做得非常出色。你可以使用这些语言以跨平台的方式完成许多事情,而无需诉诸于一小部分常见功能。 - Bryan Oakley
@Bryan:我并不忽视它们,只是认为它们是一种妥协(无论好坏)的选择,与虚拟机的影响相当。GUI是一种半高级的功能,你可以找到很多跨平台的方式来构建GUI,但这并不是一个通用的答案。通用的答案是,如果你需要每个高级功能都去寻找特定的跨平台组件,那就像是在构建自己的虚拟机 :) - Jack
@Jack:按照你的定义,就没有跨平台程序了。例如,我可以发明一个理论上图灵完备的机器,但没有可用的编译器来针对它。一个更合理、虽然有些模糊的跨平台定义是指它可以在大多数平台上运行。"大多数"的含义取决于具体情况,但对许多人来说,它意味着"可以在*nix、Windows和OS X上运行"。或许更准确的说法是,如果一个程序可以在多个平台上运行,那么它就是跨平台的。 - Staffan

1

没有特定的适用于不同平台的Java虚拟机。Java在不同平台上有不同的虚拟机,以便Java程序能够在每个平台上运行。这是一种将Java程序能够在任何地方运行的中间层。

例如,C程序可以在Windows和Linux上运行,但必须使用相应操作系统的编译器进行编译。

但在Java中,你不需要这样做。只需编译源代码,并可以分发已编译的文件,这些文件可以在任何平台上执行。


1

如果你选择一种现代脚本语言(Tcl 和 Python 是两个极好的例子),你可以编写几乎在所有平台上运行的程序。当然,你需要对某个平台进行小调整,但这很容易做到。看看那些语言,获取一些灵感。

用这些语言,你不会创建下一个 Photoshop 或第一人称射击游戏,但对于绝大多数常见的编程任务来说,它们相当适用。

如果您想要具体的东西,请参阅 http://tkdocs.com,该网站展示了 Tk 工具包在多个平台上以及使用多种语言(Tcl、Ruby、Perl、Python)的运行情况。


实际上,你可以用大部分是Python和一些可移植的C扩展来编写下一个Photoshop,以提高性能。大约80%的Adobe Lightroom及其所有插件都是用Lua编写的。而且,谷歌还有一个在JavaScript中以30+帧每秒运行的Quake版本。 - user177800

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接