Qt插件HOWTO
轉自:http://www.qiliang.net/old/qt/plugins-howto.html
?
?
| 主頁 | 所有的類 | 主要的類 | 注釋的類 | 分組的類 | 函數 |
Qt插件HOWTO
Qt提供了一個簡單地插件接口,可以輕松地生成作為獨立組件的定制數據庫驅動、圖象格式、文本編解碼器(text codec)、風格(style)和部件。
警告:Qt 3.0.5對插件的一些方面做了改變,具體涉及到裝載、路徑操作和庫版本。這些變化的結果是,Qt 3.0.4及以前版本編譯的插件都不能用于Qt 3.0.5及以后版本。
寫一個插件通過以下方式完成:寫適當的插件基類的子類,實現幾個函數,再添加一個宏。
一共有五個插件基類。派生的插件缺省保存于標準插件目錄。
?
| QImageFormatPlugin | $QTDIR/plugins/imageformats |
| QSqlDriverPlugin | $QTDIR/plugins/sqldrivers |
| QStylePlugin | $QTDIR/plugins/styles |
| QTextCodecPlugin | $QTDIR/plugins/codecs |
| QWidgetPlugin | $QTDIR/plugins/designer |
假設你有一個新的風格類,叫做'MyStyle',你要把它做成插件的形式。需要的代碼直截了當:
class MyStylePlugin : public QStylePlugin{public:MyStylePlugin() {}~MyStylePlugin() {}QStringListkeys() const { return QStringList() << "MyStyle"; }QStyle * create( const QString & key ) { if ( key == "MyStyle" ) return new MyStyle;return 0;}};Q_EXPORT_PLUGIN( MyStylePlugin )構造器和解構器不需要做什么,空的就可以。有兩個虛函數一定要實現。第一個是keys(),它返回在插件中實現的類的一個字符串列表。(我們在上面的例子中剛剛實現了一個類。)第二個是一個函數,它返回所要的類的一個對象(或者0,如果插件被要求生成一個不存在的類的對象)。對于QStylePlugin來說,這第二個函數叫做create()。
可以在一個插件里實現任意數目的插件子類,只要他們都是由同一個基類,比如說,QStylePlugin,派生出來的。
對于數據庫驅動、圖象格式、定制部件和文本編解碼器,不需要顯式的對象生成過程。Qt會按需求查找并生成他們。風格則是例外,因為你可能想以代碼顯式地設置一個風格。應用一個風格,可以使用類似代碼:
QApplication::setStyle ( QStyleFactory::create ( "MyStyle" ) );有的插件類還需要實現其他函數。關于一個QWidgetPlugin的完全例子,可參見Qt設計器手冊中'生成定制部件'一章的'生成定制部件'節。這個例子實現了額外的函數,以把該插件集成到Qt設計器中去。QWidgetFactory類提供了關于QWidgetPlugin的附加信息。
關于每種類型的插件必須要實現哪些虛擬函數,詳見該類的文檔。
Qt的應用自動辨識哪些插件可用,因為插件都是保存在標準插件子目錄下的。為此,應用不需要任何查找和裝載插件的代碼,既然Qt已自動處理了。
插件的缺省目錄是$QTDIR/plugins,每種類型的插件在那種類型的子目錄下,比如說,風格(styles)。如果你想要你的應用使用插件但不要標準插件路徑,可以讓你的安裝程序決定你要為插件使用的路徑,然后保存該路徑,比如說使用QSettings,以使應用在運行時可以讀取。之后應用可以用該路徑調用QApplication::addLibraryPath(),就可以使用你的插件了。注意,路徑的最后部分,也就是說,styles、widgets等等,不能改變。
應用包括一個插件的正規方法是,要么把插件與應用一起編譯,要么把插件編譯為DLL(或者so或者其他平臺指定的庫類型),像其他庫那樣使用。如果要讓插件可裝載,一個方法是,生成一個應用下的子目錄,例如,appdir/plugins/designer,把插件放置到該目錄下。
?
裝載與校驗插件
在裝載插件時,Qt庫做了一些穩健的檢查,以確定插件是否可以裝載和使用。這一點保證了多重版本的能力和分頭所安裝的Qt庫的配置。
- 與高一點的主版本和/或次版本的Qt庫鏈接的插件,不能被低的主版本和/或次版本的庫所裝載。(譯者注:補丁版本不限)
原因解釋:
依靠新的Qt庫而鏈接的插件可能使用了一些舊版本沒有的新特性。Trolltech有一項政策:只在次級發布(minor release)之間添加新特性和API,這就是為什么本測試只看主版本號和次版本號,不看補丁級版本號的緣故。
?
- 依靠帶有線程支持的Qt庫而鏈接的插件,只能被帶有線程支持的Qt庫所裝載。
原因解釋:
線程和非線程的Qt庫有不同的名稱。帶有線程支持的庫裝載一個依靠不帶有線程支持的Qt庫而鏈接的插件,將會導致在內存中同時有同一庫的兩個版本。在UNIX系統中,這會導致非線程Qt庫被裝載。這時,Qt庫中的所有靜態對象的構造器都會被調用第二次,但是它們是對已經在內存中的對象進行操作。沒有辦法繞過這一點,因為這是對象二進制格式的一個特征:已經被線程Qt庫定義的靜態符號,不能在被非線程Qt庫被裝載的時候被替換或者拷貝。
?
- 依靠不帶有線程支持的Qt庫而鏈接的插件,只能被不帶有線程支持的Qt庫所裝載。
原因解釋:
參見上面的解釋。
?
- 從Qt 3.0.5開始,Qt庫與所有插件都使用聯編關鍵字(build key)來聯編。Qt庫中的聯編關鍵字被與插件中的聯編關鍵字對照,如果相符,插件就被裝載。如果聯編關鍵字不符,Qt庫就拒絕裝載該插件。
原因解釋:
參見下面對于build key的解釋。
?
聯編關鍵字(build key)
聯編關鍵字包含一下信息:
- 體系結構(Architecture)、操作系統和編譯器。
原因解釋:
在同一編譯器的不同版本并不產生二進制兼容代碼的場合,編譯器的版本也體現在聯編關鍵字里。
?
- Qt的配置。這個配置是一個列表,包括了影響庫中可用到的API的那些缺少的特性。
原因解釋:
兩個同一版本的Qt庫的不同配置不是二進制兼容的。裝載插件的Qt庫使用這個(缺少的)特性列表來判斷插件是不是二進制兼容的。
注意:也存在這種情況,插件可以使用在兩個不同配置里可用到的特性。但是,編寫插件的開發者需要知道,哪些特性在他們的插件和Qt的公用工具類中都在被使用。Qt庫在裝載插件時會需要復雜的特性與依賴性的查詢確認。這些需求給開發者添了一個不必要的負擔,也增加了裝載插件的系統開銷。為了減少開發時間,降低應用的運行時消耗,可以使用對聯編關鍵字的簡單字符串比較。
?
- 可選地,可以在配置腳本命令行指定一個附加的字符串。
原因解釋:
在發布帶有應用的Qt庫的二進制時,這給開發者提供了一個辦法,來編寫只能被插件以之鏈接的那個庫所裝載的插件。
?
插件與線程應用
如果你想聯編一個使用線程Qt庫的插件(不管插件本身是否使用線程),你必須使用線程環境。具體說來,你必須用線程Qt庫鏈接插件,必須用該庫聯編Qt設計器。你用于插件的.pro文件必須包括這一行:
CONFIG += thread警告:不要在應用中混用一般的Qt庫與線程Qt庫。如果你的應用使用了線程Qt庫,你不應該用一般Qt庫鏈接你的插件,也不應該動態裝載一般Qt庫或者動態裝載依賴一般Qt庫的另一個庫,比如一個插件。在一些系統中,混用線程與非線程庫或者插件會破壞(corrupt)Qt庫中使用的靜態數據。
| Copyright ? 2002 Trolltech | Trademarks | 譯者:farfareast | Qt 3.0.5版 |
總結
- 上一篇: Qt的Oracle数据库QOCI驱动问题
- 下一篇: 因主机名更改造成oracle控制台登录错