2016-03-13 57 views
0

我的代碼應該在引入QOpenGLWidget之前和之後的平臺上編譯和運行,取代了QGLWidget。我以爲我可以寫這樣的代碼來支持:根據Qt版本動態使用QGLWidget或QOpenGLWidget

#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這將它傳遞給商務部之前運行的文件${CMAKE_CXX_COMPILER}" -E -P -x c++-header ...來解決這個問題。但是,這似乎不起作用,因爲預處理器將刪除魔術線Q_OBJECT,表明在運行C預處理器之前,必須先運行moc之前的

我還有其他選擇嗎?

我必須求助於有兩個幾乎相同的頭文件(兩行除外),然後在cmake中編譯時選擇正確的頭文件嗎?

編輯

爲了測試這個問題,請嘗試以下:

  • ,它有一個值得信賴的Ubuntu系統上QT 5.2.1(您可以創建使用sudo debootstrap trusty ubuntu-trusty一個chroot)做:
  • 的apt-get安裝libqt5opengl5-dev的建立必要的qttools5-dev的QT5默認
  • 然後創建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 interpretes預處理指令這樣

  • 我們可以改變版本檢查更簡單

    #if QT_VERSION >= 0x050400 
    
  • 如果我們再次嘗試使用該檢查,那麼在Ubuntu Trusty中的qt 5.2.1中的moc生成正確的結果

  • 因此,我們認爲我們找到了解決方案,並嘗試從相同代碼中更近期的qt分發中運行moc 。這一次,我在Debian的不穩定使用MOC從QT 5.5.1,我得到:

    $ 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我打開版本檢查宏觀麥克使用

    #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) 
    
  • 然後它工作!

因此,在總結,商務部確實瞭解一些預處理指令,但它確實瞭解的有前和Qt 5.4版本後之間的不同。似乎沒有一個通用的預處理器指令可以被兩者理解。因此我沒有看到使用預處理器指令來解決這個問題的方法。

+0

其實'moc' *確實瞭解(某些?)預處理指令。這是你的完整標題嗎? – peppe

+0

你用Qt 5.4和5.x(x <4)還是用Qt 4.x? 'moc'擴展了Qt 5中的宏。 – peppe

+0

再一次,是你的完整頭文件嗎?我想有一個完整的測試用例... – peppe

回答

1

您可以使用CMake生成此標頭。把這段代碼到其中:

#include <@[email protected]> 

class GLWidget : @[email protected] 
{ 
    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"

+0

感謝您的回答,但您可能希望編寫'public @ GL_CLASS @'作爲私有繼承對Qt小部件沒有意義。 – josch

相關問題