QT開發——動態庫/靜態庫的生成與調用(Qmake和Cmake方式)


1.理解動態庫與靜態庫區別

鏈接:https://blog.csdn.net/wonengguwozai/article/details/93195827

靜態庫和動態庫最本質的區別就是:該庫是否被編譯進目標(程序)內部。

1.1 靜態(函數)庫   

一般擴展名為(.a或.lib),這類的函數庫通常擴展名為libxxx.a或xxx.lib 。   

        這類庫在編譯的時候會直接整合到目標程序中,所以利用靜態函數庫編譯成的文件會比較大,這類函數庫最大的優點就是編譯成功的可執行文件可以獨立運行,而不再需要向外部要求讀取函數庫的內容;但是從升級難易度來看明顯沒有優勢,如果函數庫更新,需要重新編譯。  

1.2 動態函數庫   

動態函數庫的擴展名一般為(.so或.dll),這類函數庫通常名為libxxx.so或xxx.dll 。
       與靜態函數庫被整個捕捉到程序中不同,動態函數庫在編譯的時候,在程序里只有一個“指向”的位置而已,也就是說當可執行文件需要使用到函數庫的機制時,程序才會去讀取函數庫來使用;也就是說可執行文件無法單獨運行。這樣從產品功能升級角度方便升級,只要替換對應動態庫即可,不必重新編譯整個可執行文件。

1.3總結

    從產品化的角度,發布的算法庫或功能庫盡量使動態庫,這樣方便更新和升級,不必重新編譯整個可執行文件,只需新版本動態庫替換掉舊動態庫即可。
    從函數庫集成的角度,若要將發布的所有子庫(不止一個)集成為一個動態庫向外提供接口,那么就需要將所有子庫編譯為靜態庫,這樣所有子庫就可以全部編譯進目標動態庫中,由最終的一個集成庫向外提供功能。

2.qmake方式生成和調用動態/靜態庫

鏈接:https://blog.csdn.net/lywzgzl/article/details/42805991

2.1 生成庫

QT -= gui
TARGET = laser_lib
TEMPLATE = lib
CONFIG   += staticlib  #加這句是生成靜態庫,不加則是動態庫

DEFINES += LASER_LIB_LIBRARY
DEFINES += QT_DEPRECATED_WARNINGS
LIBS += /usr/lib/x86_64-linux-gnu/libboost_thread.so\
        /usr/lib/x86_64-linux-gnu/libboost_system.so

SOURCES += \
        laser_lib.cpp 

HEADERS += \
        laser_lib.h \
        laser_lib_global.h 

include(LMS1xx/LMS1xx.pri)

DESTDIR = $$PWD/../Lib

unix {
    target.path = /usr/lib
    INSTALLS += target
}

2.2 調用庫

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle
DEFINES += QT_DEPRECATED_WARNINGS

#增加系統庫的依賴
LIBS +=/usr/lib/x86_64-linux-gnu/libboost_thread.so\
        /usr/lib/x86_64-linux-gnu/libboost_system.so
#增加自定義庫的依賴
LIBS +=  -L$$PWD/../Lib -llaser_lib  #$$PWD獲取當前pro文件的目錄
INCLUDEPATH += ../laser_lib

SOURCES += main.cpp
DESTDIR = $$PWD/../Lib

3.cmake方式生成和調用動態庫

3.1創建共享庫項目

Cmake新建一個Qt Creator項目,在CMakeLists.txt中添加如下代碼

#-------------------------------------- 搜索軟件包 --------------------------------------
find_package(Qt5Widgets REQUIRED)
find_package(Qt5Network REQUIRED)
set(CMAKE_AUTOMOC ON)
#-------------------------------------- 包含頭文件 --------------------------------------
include_directories(${Qt5Widgets_INCLUDE_DIRS})
include_directories(${Qt5Network_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
#-------------------------------------- -添加項目- --------------------------------------
FILE(GLOB_RECURSE HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h*)
FILE(GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.c*)

add_library(${PROJECT_NAME} SHARED
${HEADER_FILES}
${SOURCE_FILES}
) #STATIC or SHARED 對應靜態庫 或者 動態庫

target_link_libraries(${PROJECT_NAME}
${Qt5Widgets_LIBRARIES}
${Qt5Network_LIBRARIES}
)
#-------------------------------------- -設置輸出- --------------------------------------
set(OUTPUT_LIB_DIR ${PROJECT_BINARY_DIR}/lib
    CACHE PATH "Output directory for libraries")
file(MAKE_DIRECTORY ${OUTPUT_LIB_DIR})
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/${PROJECT_NAME})
set(LIBRARY_OUTPUT_PATH     ${OUTPUT_LIB_DIR})
#-------------------------------------- -安裝項目- --------------------------------------
install(TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}
LIBRARY DESTINATION ${LIBRARY_OUTPUT_PATH}
)

按需編輯plugintest.h和plugintest.cpp,這個就是該共享庫項目的plugintest類了,我加入了一個int sum(int input1, int input2);公共函數,內容為:

int Plugintest::sum(int input1, int input2)
{
    std::cout<<"Hello World!"<<std::endl;
    int sum = input1+input2;
    return sum;
}

保存並編譯項目吧,沒問題的話會在plugintest-build/lib目錄里生成libplugintest.so。

3.2調用共享庫的項目

3.2.1再次新建Cmake新建一個Qt Creator項目,用來調用剛剛生成的庫

在項目根目錄下新建一個plugintest文件夾,把生成的庫和頭文件include文件夾全復制進去

或者把庫生成安裝到計算機系統文件夾下,這樣每次更新安裝更加方便

3.2.2在CMakeLists.txt中添加如下代碼

#-------------------------------------- 包含頭文件 --------------------------------------
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/pludintest/include)

#-------------------------------------- 引入庫文件 --------------------------------------
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/pludintest)

#-------------------------------------- -添加項目- --------------------------------------
target_link_libraries(
${PROJECT_NAME}
${Qt5Widgets_LIBRARIES}
${Qt5Network_LIBRARIES}
libplugintest.so
)

 3.2.3修改一下main.cpp調用pluginTest的sum()試試看吧

我的main.cpp內容如下:

#include <QApplication>
#include "plugintest.h"
int main(int argc, char* argv[])
{
  QApplication a(argc, argv);
  Plugintest demo;
  int sum = demo.sum(3,5);
  std::cout<<sum<<std::endl;
  return a.exec();
}

 3.2.4保存編譯項目然后運行。

不出意外就會得到Hello World!和求和8的輸出了,修改pluginTest項目的sum()函數重新編譯該共享庫,運行主程序就會得到不同的輸出結果(不用重新編譯主程序),這就是共享庫(動態鏈接庫)的好處所在。

4.常見問題解決

4.1 Qt項目在Qt Creator下編譯運行正常,但是直接執行應用程序,內建的動態庫找不到...

Qt默認檢索的動態庫路徑是/usr/lib和/lib,

保證所有的動態庫生成后都在同一個目錄下即可,手動拖也行。

然后把整個bin路徑里所有動態庫,拷貝到/usr/lib目錄下即可


免責聲明!

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



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