QT 編譯遇到重定義;不同的基類型&在QT中使用C++ lib庫


最近在使用osg和qt開發,在集成osg時候因為我使用的qt版本為非opengl的版本,導致qt自己封了一遍opengl的一些基類變量如double 這時候就會跟osg中聲明的opengl的類型沖突,提示重定義了不同的基類行。

解決方案:

使用opengl版本的qt庫 =。。=

 

在QT中使用C++編寫的lib庫 需要修改pro文件,主要問題是引用路徑的問題

image

_pro_file_pwd 代表了工程文件當前目錄

可以通過在qt creator 的幫助中 搜索 variables 來查看相關詳細介紹,或者參考一下

http://my.oschina.net/jinzei/blog/100989?p=1

  相信大家很多和我一樣,用多了微軟給的便利,用人家的就十分不習慣.於是就琢磨原來用到的功能現在要整順手來,不然可讓人怎么活啊! 本篇主要介紹實踐使用,並非一篇完整教程,有待讀者補充.^_^

    我們原本在VS上有一個大工程sln,里面有lib,有dll有exe,甚至還混搭了C#.用起來一點不覺得水土不服.現在要用QT重整,並且需要處處考慮換個平台不要讓我改東西.作為探路先鋒,先挑了幾個基礎工程出來做實驗:

    ↑當然,圖中是已經成事之后了.想在qtcreator中弄一個工程集還真不是那么方便,我到處找過了,壓根沒有創建工程集的辦法.縱使你可以一個pro一個pro的拖進去,最后也沒法保存,下次打開還得重新一個一個pro的拖,沒哪個傻蛋總這么干吧..所以首先就是要手動創建一個subdirs型的pro做為工程集,也就是上面看到的
**CloudBoard_win32.pro**(subdirs舉例)

TEMPLATE = subdirs

SUBDIRS =\
        raknet\
    onetengine \
    omisc \
    testDebugShow

onetengine.depends = raknet omisc
testDebugShow.depends = omisc
#CONFIG += ordered

    關於這個pro的詳細寫法,感覺qt文檔寫的很細碎,反正我是沒看明白.就着廣大網友的例子才有了上面一段.TEMPLATE=subdirs這是固定寫法,聲明是做工程集目錄的.SUBDIRS是指明目錄中有哪些項,可以嵌套另一個subdirs型的pro. 接下來可以詳細定義其中的項目.如.depends表示左邊的依賴=后面的項目.

.subdir
指定子項的目錄,不使用子項本身的名字.

.file
明確指定該子項使用的pro文件,默認是根據名字自動找的,該項不和.subdir同時使用

.condition
Specifies a bld.inf define that must be true for subproject to be built. Available only on Symbian platform.

.depends
該子項依賴指定的子項,只在使用makefiles的平台有效

.makefile
該子項的makefile,只在使用makefiles的平台有效

.target
該子項的TARGET,只在使用makefiles的平台有效

    以上翻譯可能有問題.重新總結一下.使用subdirs =a b c d聲明的其實是4個子項的名字.默認你不多做說明的話,qmake根據名字自動去找子目錄,啟用子目錄中的pro文件(名字優先匹配).如果你特別說明a.subdir=./z或者a.file=./z/z.pro就可以不受名字限制. 至於.makefile,應該是你混用第三方庫的時候才有必要手動指定使用的makefile. target可以在子pro中指定,除非你覺得這里比較統一方便修改.其余的未實踐不多說.

**omisc.pro**(staticlib舉例)

QT       -= gui   ①

TARGET = misc   ②
TEMPLATE = lib  #固定寫法
CONFIG += staticlib   #靜態庫固定寫法
#DEFINES +=   ③
DESTDIR = $$_PRO_FILE_PWD_/../lib  ④
SOURCES += \
    ostatic.cpp \
    odebugoutput.cpp

HEADERS += omisc.h \
    ostatic.h \
    ostringmap.hpp \
    odebugoutput.h
unix:!symbian {  ⑤
    maemo5 {
        target.path = /opt/usr/lib
    } else {
        target.path = /usr/lib
    }
    INSTALLS += target
}
①"QT"是使用的QT庫,從平時向導創建工程可以看出,QT默認是包含gui和core,如果你不用,他自動生成的就是
QT-=core gui.此處QT-=gui表示我們還用了core
②TARGET是生成目標,名字不做修飾(不加.a/.lib/.dll)的好處是讓qt幫我們加,在不同平台不用我們考慮差別.
同時這里的名字是可以前置路徑的,如../lib/misc.它會生成在相對生成目錄上一級的lib下.不過我勸你還是不要寫相對路徑了,因為在windows下會多出debug/release目錄,目錄深度不同,你換一個平台得重寫.這還有更好的辦法,后面繼續.
③DEFINES是VS里面的預定義頭,就是定義宏,哎喲總算見着熟人了~
④DESTDIR就是剛才②說的好辦法.它控制最終的輸出,相當於VS的OurDir.此處我們控制它輸出到$$_PRO_FILE_PWD_/../lib.前面$$開頭的是一個pro變量 ,存放的是工程路徑,就是CloudBoard_win32.pro的路徑,還有更多的定義參考Qt助手. 你可以用類似message($$_PRO_FILE_)的語句測試變量到底是什么值.具體使用是:寫在pro中,右鍵pro的工程執行qmake.從編譯輸出中可以看到.

⑤最后這段是自動產生的,本人實在沒有仔細研究,看樣子應該是一種指定target目錄的辦法.而unix:!symbian讓人不難想到,這是在篩選特定平台.具體的歡迎您測試后補充^_^

    raknet相信很多童鞋了解,本案簡單將其代碼編譯成staticlib,DESTDIR=$$_PRO_FILE_PWD_/../lib完工

**onetengine.pro**(動態庫舉例)

!include( ../common.pri ) {  ①
    error(" Couldn't find the common.pri file! ")
}

QT       -= gui
QT       += network xml

TARGET = netengine
TEMPLATE = lib
DESTDIR = ../bin  #基於生成目錄

INCLUDEPATH +=  ../omisc ../raknet/source  ②
DEPENDPATH += ../omisc ../raknet/source #基於工程目錄
win32:LIBS += -lWs2_32  ③
LIBS += -lmisc -lraknet

DEFINES += ONETENGINE_LIBRARY  ④

SOURCES += onetengine.cpp \
    netengine_export.cpp

HEADERS += onetengine.h\
        onetengine_global.h \
    ../include/macrodefine.h \
    ../interface/isinkfornetengine.h \
    ../interface/inetengine.h

**common.pri**(pro包含舉例)

INCLUDEPATH += ../interface ../include  ⑤
#LIBS += -L$$QTDIR/lib
LIBS += -L../../src/lib
LIBS += -L../lib
①沒錯,pro中也是可以include的,以當前文件為起點將上一層的common.pri包含進來.common.pri中的相對路徑依然以當前pro路徑為基礎.
②INCLUDEPATH是包含目錄,類似於VS中的附加包含目錄.至於 DEPENDPATH本人實事求是沒有研究不明白有什么用.歡迎補充^_^

③使用篩選器,僅在win32下增加Ws2_32.lib的導入. LIBS相當於VS中的附加依賴庫,不同的是可以通過-L指定庫目錄,-l指定庫名.其間沒有空格的哦.例如上面的LIBS+=-L../lib -lmisc就是可以到../lib中找misc庫.misc沒有說明.a還是.lib是讓qt幫我們做.你也可以指定.lib,然后通過篩選器把其他平台的也寫一下.
④提供宏定義ONETENGINE_LIBRARY是因為在向導創建動態庫的時候qtcreator幫我們定義了這樣的

 

#ifndef ONETENGINE_GLOBAL_H

#define ONETENGINE_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(ONETENGINE_LIBRARY)

#  define ONETENGINESHARED_EXPORT Q_DECL_EXPORT

#else

#  define ONETENGINESHARED_EXPORT Q_DECL_IMPORT

#endif

#endif // ONETENGINE_GLOBAL_H

提供宏定義ONETENGINE_LIBRARY決定了該工程的作用是導出動態庫的.
⑤最后common.pri只是定義了幾項公共的沒有平台差異的信息

    好了,testDebugShow的工程pro就不多說了,它和動態庫的很相似,只有TEMPLATE=app沒有XXXX_LIBRARY的宏定義而已.

    最后補充一點,為什么總的工程名要叫CloudBoard_win32呢,明眼人一看就知道這是要分平台了呢.沒錯,一開始我也覺得一個pro就搞定了,里面可以有篩選器,一份pro足以應付.但是實際是qtcreator會為pro產生同名的.user文件,qtcreator的一些配置會寫在.user里面,例如最關鍵的qtSDK位置,編譯工具,構建/生成設置等.這些必須根據生成所處的環境區別設置. 所以當你原樣跑到Linux下,啟動pro就會告訴你配置是別處讀來的,是否使用?是:配置一定是錯的,否:配置被清洗.這都不是我們希望的.所以唯有分平台建總pro了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM