2013-06-19 67 views
0

我有一個工作示例,它使用信號和插槽在Qt共享庫(dll)和Qt應用程序之間進行通信。我的問題是,這是首選的方式,還是有更好的方式來處理qt共享庫。以下是詳細信息:在Qt共享庫和Qt應用程序之間使用信號和插槽

我開發的應用程序具有偵聽網絡上的設備和更新GUI的功能。共享庫處理偵聽網絡上的設備,Qt應用程序模塊處理GUI部分。

我有使用Q_DECL_EXPORT/Q_DECL_IMPORT導出共享庫和應用程序使用的公用類的宏。這個公共類是從QObject派生的,並定義了Qt信號和時隙。這個公共類被構建爲共享庫(dll)的一部分。

Qt的應用程序加載在編譯時的共享庫和用於公共類創建一個實例,並使用該實例以建立Qt應用程序和Qt共享庫模塊之間的信號和時隙,如下所示:

Qt的期間應用程序初始化:

// Create shared libray API class instance to access dll module features. 
mp_sharedlib_api = new shareLibAPIClass(this); 

後來在Qt應用程序:

// Connect signal/slot between shared library and Qt application 
connect(
    mp_sharedlib_api , SIGNAL(SignalUpdateGUIStatus(QString)), 
    this, SLOT(SlotUpdateGUIStatus(QString)) 
    ); 

這是d的正確方法開發一個使用共享庫的Qt項目?共享庫的API文檔包含哪些內容? API文檔是否列出了共享庫發送/處理的信號和插槽?

在此先感謝。

+0

我想你忘記了Qt本身就是一個共享庫。那麼爲什麼你會認爲信號和共享庫可能會有問題呢? –

回答

4

您不應該想到通過信號和插槽連接的兩個庫,而是一組類/類實例,一組後端相關的類和一組與UI相關的類。 UI類使用後端類(但從來沒有其他方法)。這兩組類位於不同的庫中是部署的實現細節,並且在C++級別上與應用程序設計無關。即使所有代碼在單個應用程序中鏈接在一起,設計概念也是一樣的。

使用單個信號signalUpdateGUIStatus(QString)的單個「通用類」最有可能是錯誤的方法。僅僅因爲它是一個單獨的庫,將接口限制爲單個類或甚至信號是毫無意義的。小接口是好的 - 但除非你的後端代碼只發送一種非常特定的更新,「signalUpdateUIStatus(QString whatChangedEncodedAsString)」將通過單個類/信號做太多的事情。signalUpdateGUIStatus還意味着後端庫知道有一個用戶界面。它不應該。它只是提供有關網絡設備的信息 - 無論是顯示信息的用戶界面,還是通過電子郵件發送通知(或其他任何內容)的bot都不是它的業務。

你可以有一個共享庫,如LightSensorListener,TemperatureSensorListener等等(或者只是DeviceListener,depends),它們可能是QObject在值發生變化時發出信號,但也有其他的Q_PROPERTYs,方法等。類將在應用程序中實例化,然後連接到UI代碼。

想想你如何在你的應用程序中使用Qt。您的圖書館將成爲您用來從網絡獲取數據的另一個圖書館。就像你使用QString,QWidget,QLineEdit等一樣創建和使用的UI交互,你會用你的庫的類與網絡接口:

比方說,我們的圖書館「富」有一類溫度傳感器節:

//file TemperatureSensor.h 

/** 
    * A temperature sensor on the network. 
    * yaddayaddayadda 
    */ 
class FOO_EXPORT TemperatureSensor { 
     Q_OBJECT 
     Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged) 
     Q_PROPERTY(bool available READ available NOTIFY availableChanged) 
     Q_PROPERTY(qreal temperature READ temperature NOTIFY temperatureChanged) 
public: 
     /** 
     * Creates a temperature sensor 
     * 
     * @param parent parent QObject 
     */ 
     explicit TemperatureSensor(QObject* parent=0); 

     /** 
     * Returns whether the device is currently available and delivering data 
     */ 
     bool available() const; 
     /** 
     * Returns the temperature reported by the sensor (In Celsius) 
     */ 
     qreal temperature() const; 

     /** 
     * Makes the device explode. Use with caution! 
     * Don't give this to little developers/children. 
     */   
     void blowUp(); 

     //address(), setAddress() etc... 
Q_SIGNALS: 
     /** 
     * The availability of the sensor changed 
     * 
     * @param available whether the sensor is now available 
     */ 
     void availableChanged(bool available); 
     void temperatureChanged(qreal); 
     void addressChanged(const QString&); 
}; 

然後應用程序,你剛剛創建的實例和鉤他們與你的用戶界面:

TemperatureSensor sensor; 
sensor.setAddress("/tempsensors/1234"); 

TemperaturWidget widget; 
widget.show(); 
//connect signals from sensor, or pass the whole sensor instance, etc. 

有關文檔,所有公共類(也就是出口即一切)庫的應記錄在案。信號/插槽通常與其他「正常」方法一樣被記錄。

+0

感謝您提供深入的解釋。 – Rak

+0

謝謝。我的共享庫包含其他類,並在設備發現旁邊執行其他任務。但共享庫僅將包含多個信號的'shareLibAPIClass'類導出到應用程序模塊。我認爲我的實現符合您的解釋,因爲我正在創建導出類的實例,併爲來自該導出類的信號連接插槽。我應該使用信號的一般術語(避免GUI術語)。我看到的唯一問題是我有一個從應用程序到共享庫的信號,它啓動了設備配置。不知道該如何處理。有什麼建議? – Rak

+0

通過從應用程序到庫的信號/插槽觸發搜索就好了。我可能還會添加一些屬性,以提供關於狀態(「空閒」,「搜索」)和潛在錯誤的信息。 –