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

时间:2016-03-13 11:00:35

标签: c++ qt cmake c-preprocessor moc

我的代码应该在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似乎不理解预处理程序指令并且会为错误的类生成代码。

我尝试通过向add_custom_command添加CMakeLists.txt指令来解决此问题,该指令会在将文件传递给moc之前对文件运行${CMAKE_CXX_COMPILER}" -E -P -x c++-header ...。但是这似乎无法正常工作,因为预处理器将删除神奇的Q_OBJECT行,表明在运行C预处理器之前必须运行<{1}}

我还有其他选择吗?

我必须使用两个几乎相同的头文件(除了两行),然后在构建时在cmake中选择正确的头文件吗?

修改

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

  • 在qt 5.2.1附带的Ubuntu可信系统上(你可以使用moc创建一个chroot):
  • apt-get install libqt5opengl5-dev build-essential qttools5-dev qt5-default
  • 然后创建包含以下内容的sudo debootstrap trusty ubuntu-trusty

    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
    
  • 所以你看到即使qt 5.2.1没有QOpenGL,moc也会解释预处理器指令

  • 我们可以将版本检查更改为更简单的

    $ 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!
    
  • 如果我们再次使用该检查,那么在Ubuntu trusty中的qt 5.2.1中的moc会生成正确的结果

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

    #if QT_VERSION >= 0x050400
    
  • 最有趣的是,如果在qt 5.5.1下我将版本检查宏mack转为使用

    $ 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
    
  • 然后它确实有效!

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

1 个答案:

答案 0 :(得分:1)

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

#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"