平台独立与C ++。 检测和编译
所以我想建立我的应用程序,使其成为独立平台,以便它可以在Windows,OSX,Linux等上运行。
例如,跨平台不同的主要“部分”之一是窗口。 在Windows上它将使用Win32 API,并且在OSX上,Linux我想它会使用别的东西。
我有一个IWindow.h类,它是一个与Window交互的接口和一个封装所有Win32函数并扩展IWindow接口的MSWindow类。
将来我会创建一个OSXWindow类等等
所以我的两个问题是:
#ifdef RUNNING_WINDOWS #include #elif RUNNING_OSX #include #endif
//m_window is declared as IWindow* m_window; #ifdef RUNNING_WINDOWS m_window = new MSWindow(); #elif RUNNING_OSX m_window = new OSXWindow(); #endif
很明显,RUNNING_WINDOWS和RUNNING_OSX是如此组成的,所以如果有人知道实际的标志,我可以查找,将不胜感激。
//Main Entry point to windows application 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
有可能我会这么想,所以希望这是你可以进来的地方,让我走上正确的道路。
谢谢!
编辑:
根据下面的评论,我会添加更多关于我的目标的信息。
基本上我有一个核心类,这是我的应用程序。 我的main.cpp实例化了这个Core类的一个实例,这就是它。
Core类将拥有一个Window类的实例。 Core不应该关心它是什么样的Window,它只是需要与它进行交互。
然后,我收集的窗口本身(从下面的评论)将在内部处理平台独立性方面的问题。 所以Window可能因为#ifdef块而变得混乱,但应用程序的其余部分以及任何与Window交互的内容都不在意。
我采取的另一种选择和第一个方向是,对于从常见IWindow接口派生而来的每个“类型”Window实现,都有单独的类。 然后,#ifdefs将发生在Core中,实例化和包含哪种类型。 虽然这将操作系统的实现分离出来,但我同意它会干扰Core,如果应用程序的其他未来部分需要引用该窗口,则还需要#ifdef块,这将导致整体代码变得更加混乱。
真的,最好的方法是通过创建一个包装Window的类来封装Window的整个概念。 然后这个类可以通过非API特定的函数提供所需的接口,所以使用它的东西甚至不需要知道Win32 API或GTK或其他窗口系统的工作方式。 简而言之,您不希望每次需要启动窗口时都使用#ifdef
,但希望将它们隐藏在其他类中。 我已经使用Qt Framework作为一个非常强大的跨平台框架,并且可以在Windows,Mac,Linux和其他平台上编译相同的C ++。 它提供对Windowing系统,网络连接,线程,媒体播放,文件系统访问等的跨平台标准化访问。
如果你真的想重新发明轮子并编写你自己的包装类,你应该看看定义的编译器特定的宏,以确保你想支持的平台已经到位。 这里有一个很好的地方可以查看什么编译器在什么平台上定义了哪些宏。 一些常见的宏是用于Visual Studio编译的_WIN32和用于基于Unix的平台的__unix__。
我做了这样的事情,所以我可以提供一些建议。
尽管可以调用Window类MSWindow,OSXWindow等,但这实际上并不方便,因为需要与Window进行交互的代码的每个部分都需要知道使用哪一个。 你应该只把这些类叫做Window。 由于您只会在给定的平台上编译其中的一个,因此不会发生碰撞。
检查给定操作系统的宏:
_WIN32
for Windows __APPLE__
适用于OSX和iOS(我设置自己的常量以在pch文件中区分这两个) __linux__
for Linux 我建议你不要在上面的地方添加#define
。 如果您将跨平台特定代码放置在尽可能少的地方,您将拥有更多可移植代码。
您将在每个平台上拥有不同的主要功能。 WinMain()
在Windows上, main()
在其他上。 我建议您将这些文件放在不同的文件中,并且只能在makefile或项目文件中引用与正确平台相对应的文件。
你问的HINSTANCE问题很容易解决。 在你的WinMain()函数中,你将把HINSTACE赋予你的Window类。 Windows上的Window类将有一个静态方法,比如setHinstance()
,它将把HINSTACE存储在一个类变量中。 然后,当创建一个Window实例时,HINSTACE将可用,而无需更改此类的常用方法。
作为最终评论,您应该记住,有几个跨平台的GUI框架可能适合您。 如果你想要一个全功能的,那么看看Qt。 如果你想要一个非常简单的(有一些很好的功能,但不像Qt那么多),那么看看FLTK。 Qt和FLTK都是开源的。
上一篇: Platform Independence with C++. Detection and Compilation