c++的平台独立性.检测和编译
Platform Independence with C++. Detection and Compilation
所以我想建立我的应用程序是平台独立的,这样它就可以运行在Windows, OSX, Linux等。
例如,不同平台的主要"部件"之一是windows。在Windows上,它会使用Win32 API,而在OSX, Linux上,我猜它会使用其他东西。
我有一个IWindow.h类,它是一个与windows交互的接口,还有一个MSWindow类,它封装了所有的Win32函数并扩展了IWindow接口。
以后我会创建一个OSXWindow类等等等等
所以我的两个问题点是:
- 在某些时候,我需要检测我正在运行的平台并实例化正确的类。我想我将不得不为包含做一些ifdef块,然后也是实例化本身?
显然RUNNING_WINDOWS和RUNNING_OSX是组成的,所以如果有人知道实际的标志,我可以查找,将是感激的。
- 我的main.cpp入口点目前在Windows上。
并且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 - Windows
我建议你不要在上面所有的地方添加#define
。如果你把跨平台的特定代码放在尽可能少的地方,你会有更多的可移植代码。
您将在每个平台上拥有不同的主要功能。Windows为WinMain()
,其他为main()
。我建议您将这些文件放在不同的文件中,并且只引用makefile或项目文件中对应于正确平台的文件。
你问的HINSTANCE问题很容易解决。在你的WinMain()函数中,你将给你的Window类一个HINSTACE。Windows上的Window类将有一个静态方法,比如setHinstance()
,它将把HINSTACE存储在一个类变量中。然后,当一个窗口实例被创建时,HINSTACE将是可用的,而不必改变该类的公共方法。
作为最后的评论,您应该记住有几个跨平台的GUI框架可能适合您。如果你想要一个功能齐全的,那就看看Qt,如果你想要一个非常简单易用的(有一些不错的功能,但没有Qt那么多),那就看看FLTK。Qt和FLTK都是开源的
- 编译的C可执行文件被Windows defender检测为病毒
- CodeLite 不会检测(安装)MinGW - 即使使用手动配置也不会编译
- 检测编译时文本和常量
- 如何在编译时检测C 17中是否没有虚拟基础
- 有没有办法在编译时检测是否可以使用一组给定的参数类型成功调用通用 lambda?
- 编译时未检测到主要功能
- 参数类型的编译时类型检测
- 使用SFINAE检测编译时间是否存在过载的独立式功能
- 如何在编译时检测 C++ 代码中的 SQL 错误
- 如何在编译时检测ABI
- 我可以检测编译时使用的标记调度重载吗?
- 如何检测编译时是否shared_ptr类型
- 检测或避免在编译时间上暂时提及暂时的提及
- 在编译时检测std :: size_t类型以调用正确的功能
- 编译共享对象时出错:未检测到C++类定义
- 在编译时检测是否存在默认构造函数
- 编译弃用电话的时间检测
- 是否可以在编译时间作为宏上检测GCC编译标志
- 编译时解决方案以检测特征对象没有eval()成员
- 使用模板组合进行 CRTP 编译检测