c++的平台独立性.检测和编译

Platform Independence with C++. Detection and Compilation

本文关键字:编译 检测 独立性 平台 c++      更新时间:2023-10-16

所以我想建立我的应用程序是平台独立的,这样它就可以运行在Windows, OSX, Linux等。

例如,不同平台的主要"部件"之一是windows。在Windows上,它会使用Win32 API,而在OSX, Linux上,我猜它会使用其他东西。

我有一个IWindow.h类,它是一个与windows交互的接口,还有一个MSWindow类,它封装了所有的Win32函数并扩展了IWindow接口。

以后我会创建一个OSXWindow类等等等等

所以我的两个问题点是:

    在某些时候,我需要检测我正在运行的平台并实例化正确的类。我想我将不得不为包含做一些ifdef块,然后也是实例化本身?
<>之前# ifdef RUNNING_WINDOWS# include# elif RUNNING_OSX# include# endif之前<>之前//m_window被声明为IWindow* m_window;# ifdef RUNNING_WINDOWSm_window = new MSWindow();# elif RUNNING_OSXm_window = new OSXWindow();# endif之前

显然RUNNING_WINDOWS和RUNNING_OSX是组成的,所以如果有人知道实际的标志,我可以查找,将是感激的。

  1. 我的main.cpp入口点目前在Windows上。
<>之前//windows应用程序的入口点int WINAPI WinMain(HINSTANCE HINSTANCE, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {之前

并且hInstance必须传递给MSWindow类。这带来了一点问题,我的IWindow界面不能接受HINSTANCE,因为HINSTANCE是Windows的一部分,在OSX或Linux上不存在。我会在main.cpp中设置被ifdefs阻塞的单独入口点函数吗?

和IWindow有一个Init函数,在不同的参数基于ifdefs以及?

#ifdef RUNNING_WINDOWS
bool Init(HINSTANCE* hInstance);
#elif RUNNING_OSX
bool Init(Whatever OSX needs);
#endif

有可能我做错了,所以希望你能介入,引导我走上正确的道路。

谢谢!

编辑:

根据下面的评论,我将添加一些关于我的目标的更多信息。

本质上我有一个Core Class,它是我的应用程序。我的main.cpp实例化了这个Core类的一个实例,差不多就是这样了。

Core类将有一个Window类的实例。核心根本不应该关心它是什么样的窗口,它只需要与它交互。

窗口本身(从下面的评论),我收集将处理平台独立性方面的内部对自己。因此,由于#ifdef块,窗口可能会很混乱,但应用程序的其余部分和任何与窗口交互的东西都不会在意。

另一种选择,也是我采取的第一个方向是,为派生自公共IWindow接口的每种"类型"的窗口实现提供单独的类。然后,#ifdefs将在Core中发生,用于实例化和包含哪种类型。虽然这将跨操作系统的实现分开,但我同意它确实会使核心变得混乱,如果应用程序的任何其他部分需要引用窗口,它也需要有#ifdef块,这只会导致整体代码更加混乱。

实际上,最好的方法是通过创建一些包装窗口的类来封装窗口的整个概念。这个类可以通过非API特定的函数提供所需的接口,因此使用它的东西甚至不需要知道Win32 API, GTK或任何其他您将要使用的窗口系统是如何工作的。简而言之,您不希望每次需要初始化窗口时都必须使用#ifdef,而是希望将它们隐藏在其他类中。我使用Qt框架作为一个非常强大的跨平台框架,它可以做到这一点,并允许在Windows, Mac, Linux和其他平台上编译相同的c++。它提供了对windows系统、网络连接、线程、媒体播放、文件系统访问等的跨平台标准化访问。

如果您真的想重新发明轮子并编写自己的包装器类,则应该查看定义的特定于编译器的宏,以确保您想要支持的平台已经就绪。这里是查找哪些编译器在哪些平台上定义了哪些宏的好地方。一些常见的宏是用于Visual Studio编译的_WIN32和用于基于Unix的平台的__unix__。

我曾经做过这样的事情,所以我可以提供一些建议。

  • 虽然它可以调用你的窗口类MSWindow, OSXWindow等,这真的不方便,因为每一部分的代码,曾经需要与窗口交互将需要知道哪一个使用。你应该只调用这些类Window。因为你只会在一个给定的平台上编译其中的一个,所以没有冲突。

  • 检查给定操作系统的宏:

    • Windows _WIN32
    • __APPLE__用于OSX和iOS(我在pch文件中设置了自己的常量来区分这两个)
    • __linux__ for Linux
  • 我建议你不要在上面所有的地方添加#define。如果你把跨平台的特定代码放在尽可能少的地方,你会有更多的可移植代码。

  • 您将在每个平台上拥有不同的主要功能。Windows为WinMain(),其他为main()。我建议您将这些文件放在不同的文件中,并且只引用makefile或项目文件中对应于正确平台的文件。

  • 你问的HINSTANCE问题很容易解决。在你的WinMain()函数中,你将给你的Window类一个HINSTACE。Windows上的Window类将有一个静态方法,比如setHinstance(),它将把HINSTACE存储在一个类变量中。然后,当一个窗口实例被创建时,HINSTACE将是可用的,而不必改变该类的公共方法。

  • 作为最后的评论,您应该记住有几个跨平台的GUI框架可能适合您。如果你想要一个功能齐全的,那就看看Qt,如果你想要一个非常简单易用的(有一些不错的功能,但没有Qt那么多),那就看看FLTK。Qt和FLTK都是开源的