c++ - 根据 Qt 版本动态使用 QGLWidget 或 QOpenGLWidget

标签 c++ qt cmake c-preprocessor moc

我的代码应该在 Qt 5.4 之前和之后的平台上编译和运行,Qt 5.4 引入了 QOpenGLWidget,取代了 QGLWidget。我以为我可以编写这样的代码来支持两者:

#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
#  define USE_Q_OPEN_GL_WIDGET
#endif

#ifdef USE_Q_OPEN_GL_WIDGET
#  include <QOpenGLWidget>
#else
#  include <QGLWidget>
#endif

class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
    public QOpenGLWidget
#else
    public QGLWidget
#endif
{
    Q_OBJECT
public:
    [...]

但这不会成功,因为 moc 似乎不理解预处理器指令,并且会为错误的类生成代码。

我试图通过向我的 CMakeLists.txt 添加一个 add_custom_command 指令来解决这个问题,它将运行 ${CMAKE_CXX_COMPILER}"-E -P - x c++-header ... 在将文件传递给 moc 之前。但这似乎也不起作用,因为预处理器将删除神奇的 Q_OBJECT 行,表明确实 moc 必须在 C 预处理器运行 之前运行。

我还有哪些其他选择?

我必须求助于拥有两个几乎相同的头文件(两行除外),然后在构建时在 cmake 中选择正确的头文件吗?

编辑

要测试这个问题,请尝试以下操作:

  • 在带有 qt 5.2.1 的 Ubuntu 可信系统上(您可以使用 sudo debootstrap trusty ubuntu-trusty 创建一个 chroot)做:
  • apt-get install libqt5opengl5-dev build-essential qttools5-dev qt5-default
  • 然后创建 glwidget.h 包含:

    #ifndef GLWIDGET_H
    #define GLWIDGET_H
    
    #include <QtGlobal>
    #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
    #  define USE_Q_OPEN_GL_WIDGET
    #endif
    
    #ifdef USE_Q_OPEN_GL_WIDGET
    #  include <QOpenGLWidget>
    #else
    #  include <QGLWidget>
    #endif
    
    class GLWidget :
    #ifdef USE_Q_OPEN_GL_WIDGET
        public QOpenGLWidget
    #else
        public QGLWidget
    #endif
    {
        Q_OBJECT
    };
    #endif
    
  • 然后运行:

    $ moc -v
    moc 5.2.1
    $ moc glwidget.h | grep QGL || echo "not found"
    not found
    $ moc glwidget.h | grep QOpenGL >/dev/null && echo "found!"
    found!
    
  • 所以你看到即使 qt 5.2.1 没有 QOpenGL,moc 也以这种方式解释预处理器指令

  • 我们可以将版本检查变得更简单

    #if QT_VERSION >= 0x050400
    
  • 如果我们再次尝试进行该检查,那么 Ubuntu trusty 中 qt 5.2.1 中的 moc 会生成正确的结果

  • 因此我们认为我们找到了解决方案,并尝试在同一代码上从更新的 qt 发行版运行 moc。这次我在 Debian unstable 中使用来自 qt 5.5.1 的 moc,我得到:

    $ moc -v
    moc 5.5.1
    $ moc glwidget.h | grep QOpen || echo "not found"
    not found
    $ moc foo.h | grep QGL > /dev/null && echo "found"
    found
    
  • 最有趣的是,如果在 qt 5.5.1 下,我将版本检查宏 mack 改为 using

    #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
    
  • 然后它就起作用了!

所以总而言之,moc 确实理解一些预处理器指令,但它理解的指令在 qt 5.4 之前和之后的版本之间是不同的。似乎不存在两者都能理解的通用预处理器指令。因此,我看不到使用预处理器指令解决此问题的方法。

最佳答案

您可以使用 CMake 生成此 header 。将此代码放入其中:

#include <@GL_CLASS@>

class GLWidget : @GL_CLASS@
{
    Q_OBJECT
public:
    [...]

然后在 CMakeLists.txt 中执行此操作:

set(GL_CLASS <depending on Qt version>)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) #this is because configure_file produces its output in the build dir
configure_file(yourheader.h output.h @ONLY)

最后,在您的代码中使用#include "output.h"

关于c++ - 根据 Qt 版本动态使用 QGLWidget 或 QOpenGLWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35969392/

相关文章:

c++ - C++ 跨平台编程

c++ - 在 C++ 2 中处理 int 数组

c++ - 覆盖对话框关闭时的 QWidget 事件?

qt - Qt 中的这个小部件叫什么?

c++ - 从 MainWindow 移动到函数时替换 THIS

c++ - CMake 在更改时不会重新编译源文件?

C++线程本地计数器实现

c++ - 在文本文件中查找(“)c++

c++ - 交叉编译时如何处理依赖关系

linux - ccmake。与 ccmake [路径]