Qt 創(chuàng)建 shared library

2018-10-08 10:00 更新

創(chuàng)建 shared library

前段時(shí)間說(shuō)了Qt一些類(lèi)庫(kù)的使用,今天來(lái)?yè)Q一下口味,來(lái)看一下程序設(shè)計(jì)的問(wèn)題。今天來(lái)說(shuō)的是關(guān)于共享庫(kù) shared library。

如果你打開(kāi)一些 Windows 應(yīng)用程序的目錄,你會(huì)發(fā)現(xiàn)有很多程序的 exe 文件都很小,大約幾百K 的樣子,并且目錄中不僅僅只有一個(gè) exe 文件,還包含著一大堆 dll 文件。這些 dll 其實(shí)就是一些共享庫(kù),所謂共享庫(kù),其實(shí)就是一些動(dòng)態(tài)鏈接庫(kù),能夠由程序在運(yùn)行時(shí)進(jìn)行動(dòng)態(tài)加載的庫(kù)。既然說(shuō)是共享,那就是說(shuō),這些庫(kù)不僅僅自己的程序可以使用,并且其他程序也可以使用,例如某些通用算法。如果你發(fā)布一下自己編寫(xiě)的 Qt 程序,也會(huì)看到很多系統(tǒng)的共享庫(kù),就是那些 QtGui.dll 之類(lèi)的東西?;蛟S你會(huì)說(shuō),我寫(xiě)的程序沒(méi)有同其他應(yīng)用共享的庫(kù),就不需要這些了吧!其實(shí)不然。因?yàn)楣蚕韼?kù)的一個(gè)好處是可以動(dòng)態(tài)加載,也就是說(shuō),如果你需要升級(jí)程序,那么就要簡(jiǎn)單的替換掉這個(gè) dll 就好了,不需要要求用戶(hù)重新安裝全部文件。當(dāng)然,這些 dll 也是有缺點(diǎn)的:動(dòng)態(tài)加載的東西肯定會(huì)比靜態(tài)編譯的東西效率低一些。不過(guò)在現(xiàn)在的硬件環(huán)境下,這點(diǎn)性能損失已經(jīng)可以忽略不計(jì)了。

今天我們要說(shuō)的就是如何用 Qt 創(chuàng)建共享庫(kù)代碼。

我們還是使用 QtCreator。在創(chuàng)建工程的時(shí)候,我們選擇下面的 C++ Library 一項(xiàng),然后點(diǎn)擊 OK。

在接下來(lái)的對(duì)話(huà)框中,有一個(gè)下拉列表,分別是 Shared Library(共享庫(kù)),Statically Linked Library(靜態(tài)鏈接庫(kù))和 Qt 4 Plugin(Qt 4 插件)。我們選擇第一個(gè)共享庫(kù),后面的步驟中會(huì)要求選擇加入哪幾個(gè) Qt 模塊,和前面一樣,選擇自己需要的部分,最后完成工程的創(chuàng)建。

我們會(huì)看到 QtCreator 已經(jīng)幫我們創(chuàng)建好了一些文件。其中有一個(gè) {projectName}_global.h 的文件是 QtCreator 替我們創(chuàng)建的。下面我們就從這個(gè) {projectName}_global.h 開(kāi)始:


#ifndef LIB_GLOBAL_H  
#define LIB_GLOBAL_H  

#include <QtCore/qglobal.h>  

#if defined(LIB_LIBRARY)  
#  define LIBSHARED_EXPORT Q_DECL_EXPORT  
#else  
#  define LIBSHARED_EXPORT Q_DECL_IMPORT  
#endif  

#endif // LIB_GLOBAL_H  

這個(gè)文件中只是定義了兩個(gè)宏 LIBSHARED_EXPORT,注意這里的 LIB 就是我的工程名字。如果定義了 LIB_LIBRARY,LIBSHARED_EXPORT 定義為 Q_DECL_EXPORT,否則定義為 Q_DECL_IMPORT??催@個(gè)名字,就知道這就是把對(duì)象導(dǎo)出的語(yǔ)句了。下面我們來(lái)編寫(xiě)一個(gè)窗口(如果你希望這么做,不要忘記在創(chuàng)建工程時(shí)勾選 QtGui 模塊,默認(rèn)是不勾選的):

lib.h


#ifndef LIB_H  
#define LIB_H  

#include <QMainWindow>  

#include "lib_global.h"  

class LIBSHARED_EXPORT MainWindow : public QMainWindow {  
public:  
    MainWindow(QWidget *parent = 0);  
};  

#endif // LIB_H 

lib.cpp


#include "lib.h"  

MainWindow::MainWindow(QWidget *parent)  
    : QMainWindow(parent)  
{  
} 

代碼很簡(jiǎn)單,就是創(chuàng)建一個(gè) MainWindow。同前面的代碼唯一不同的是,在頭文件中,使用了 LIBSHARED_EXPORT 這個(gè)宏。你可以簡(jiǎn)單的把它理解成,我需要把這個(gè)類(lèi) MainWindow 導(dǎo)出。所謂導(dǎo)出,就是將其編譯成一個(gè) dll 文件之后,其他的類(lèi)可以使用這個(gè)導(dǎo)出類(lèi)。好了,下面和原來(lái)一樣,編譯一下這個(gè)工程。在 debug 文件夾下你得到的是一個(gè) lib.dll 文件和 liblib.a。后者是 Linux 下使用的庫(kù),這里不再詳述。

好了,我們要去使用這個(gè) dll 了。新建另外一個(gè)工程,需要吧 .pro 文件修改一下:


TARGET = test  
TEMPLATE = app  

SOURCES += main.cpp  

INCLUDEPATH += ../  

LIBS += ../debug/lib.dll 

首先,我們添加了 INCLUDEPATH 這一行。這一行就是為了讓我們的 test 項(xiàng)目可以找到 lib.h 和 lib_global.h 這兩個(gè)文件,你需要把這里的路徑替換成符合你的工程的路徑。LIBS 這一行則需要告訴編譯器(注意,這里是編譯器?。┑侥睦锶フ业竭@個(gè) dll 文件。然后我們編寫(xiě) main.cpp:


#include <QtGui/QApplication>  
#include "lib.h"  

int main(int argc, char *argv[])  
{  
    QApplication a(argc, argv);  
    MainWindow w;  
    w.show();  
    return a.exec();  
}  

注意,我們使用了 lib.h,但是這個(gè)文件并沒(méi)有在 HEADERS 里面聲明,Qt 實(shí)際上就是從 INCLUDEPATH 這里去找到這個(gè)文件。MainWindow 在新建的 test 工程中并沒(méi)有聲明,那么它在哪里呢?當(dāng)然就是在我們編譯出來(lái)的 lib.dll 里面啦!我們知道,在鏈接的時(shí)候編譯器需要找到實(shí)現(xiàn)入口,也就是必須定位到這個(gè) dll,這就是由這個(gè) LIBS 指定的地方。

最后編譯運(yùn)行一下這個(gè) exe 文件,怎么樣?哦,如果你照我說(shuō)的做了的話(huà),你應(yīng)該得到一個(gè)錯(cuò)誤:找不到 lib.dll。怎么會(huì)找不到呢?不是使用 LIBS 指定了嗎?請(qǐng)注意,我們強(qiáng)調(diào)了,這個(gè)指定是編譯期的。dll 是動(dòng)態(tài)鏈接庫(kù),也就是說(shuō),在 exe 運(yùn)行的時(shí)候需要找到這個(gè)庫(kù)。運(yùn)行時(shí)查找的順序是:當(dāng)前路徑 -> 系統(tǒng)路徑(通常是 system32)。所以,要把我們先前生成的這個(gè) lib.dll 復(fù)制到 exe 所在目錄,然后直接雙擊一下這個(gè) exe 文件。一個(gè)窗口出來(lái)了!有什么區(qū)別嗎?運(yùn)行起來(lái)是沒(méi)有區(qū)別的,但是我們知道,這個(gè)窗口是在這個(gè) dll 里面實(shí)現(xiàn)的!我們想往窗口里面加個(gè)按鈕?沒(méi)問(wèn)題,那就加吧!加完之后重新編譯一個(gè)新的 dll,復(fù)制到 exe 文件夾覆蓋舊的,修改就完成啦!我們不需要修改這個(gè) exe 了。

這個(gè)時(shí)候我們?cè)賮?lái)回憶一下,我們使用自己創(chuàng)建的 dll 的時(shí)候,是不是就和使用 QtGui.dll 一樣呢?只不過(guò)QtGui.dll 已經(jīng)放在了庫(kù)目錄下, 不需要手動(dòng)修改 .pro 文件添加 INCLUDEPATH 和 LIBS 罷了。

本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/193918

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)