静态库、动态库、QT Plugin的创建与应用

    技术2025-11-20  21

    静态库、动态库、QT Plugin的创建与应用

    1. 什么是静态库、动态库、QT Plugin2. Windows下静态库、动态库的创建与使用2.1 Windows下使用VS创建静态库并使用2.1.1 创建静态库2.1.2 使用静态库 2.2 Windows下使用VS创建动态库并使用2.2.1 创建动态库2.2.2 使用动态库 2.3 小结 3. Linux下静态库、动态库的创建与使用4. QT下静态库、动态库及Plugin的创建与使用4.1 QT下静态库的创建与使用4.1.1 创建静态库4.1.2 使用静态库 4.2 QT下动态库的创建与使用4.2.1 创建动态库4.2.2 使用动态库 4.3 QT下Plugin的创建与使用4.3.1 高级插件4.3.2 底层插件4.3.2.1 项目环境搭建4.3.2.2 定义插件接口4.3.2.2 实现插件定义4.3.2.3 实现插件调用

    1. 什么是静态库、动态库、QT Plugin

    静态库、共享库可参见Linux下静态库、共享库的创建与应用静态库-百度百科动态库-百度百科QT Plugin 类型WindowsLinux静态库.lib.a动态库.dll.so

    2. Windows下静态库、动态库的创建与使用

    原文链接:https://blog.csdn.net/wallaceli1981/article/details/5740718

    2.1 Windows下使用VS创建静态库并使用

    2.1.1 创建静态库

    新建项目Visual C++|桌面|静态库新建staticLib.h、static_lib.h.cpp //static_lib.h: int add(int x, int y); int substract(int x, int y); //static_lib.cpp: #include "stdafx.h" #include "static_lib.h" int add(int x, int y) { return x + y; } int substract(int x, int y) { return x - y; } 生成解决方案,生成static_lib.lib静态库文件

    2.1.2 使用静态库

    新建Visual C++|桌面|Windows控制台应用程序将staticLib.h、static_lib.lib拷贝至main函数文件同一目录下修改main函数文件 // UseStaticLib.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include "pch.h" #include <iostream> #include "static_lib.h" //添加静态库 #pragma comment(lib, "StaticLib.lib") using namespace std; int main() { cout << add(3, 4) << endl; cout << substract(5, 3) << endl; return 0; }

    2.2 Windows下使用VS创建动态库并使用

    2.2.1 创建动态库

    新建项目Visual C++|桌面|动态链接库 // Dll.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" //Dll.cpp #define DLL_API _declspec(dllexport) #include <iostream> using namespace std; DLL_API int add(int a, int b) //实现两个整数相加 { return a + b; } DLL_API int subtract(int a, int b) //实现两个整数相减 { return a - b; } 生成解决方案,生成Dll.dll、Dll.lib动态库文件

    2.2.2 使用动态库

    新建Visual C++|桌面|Windows控制台应用程序将Dll.dll、Dll.lib拷贝至main函数文件同一目录下修改main函数文件 #include "pch.h" #include <iostream> using namespace std; #pragma comment(lib, "DLL.lib") extern int add(int a, int b); extern int subtract(int a, int b); int main() { cout << add(3, 4) << endl; cout << subtract(5, 3) << endl; return 0; }

    2.3 小结

    两个lib文件

    我们发现,无论是静态链接库还是动态链接库,最后都有lib文件,那么两者区别是什么呢?其实,两个是完全不一样的东西。staticCai.lib的大小为4KB,dllCai.lib的大小为2KB,静态库对应的lib文件叫静态库,动态库对应的lib文件叫导入库。实际上静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

    对于静态链接库,我们在编译和链接的时候已经将所有的代码都导入进来,因此,当生成可执行文件以后,可执行文件包含所有的代码。因此,在可执行文件运行时就不再需要静态库了,这也是为什么我们删掉staticCai.lib程序照样执行;而对于动态链接库,实际上,可执行文件不包含DLL中的内容,只是通过导入库(.lib)知道了相应的地址信息,因此,可执行文件在运行时动态得去加载DLL,这也是为什么我们删掉dllCai.dll后程序就不能执行了。

    对于DLL,我们是可以不要lib文件的。

    如果不要lib文件,我们可以通过函数指针的使用达到我们的目的: #define DLL_API _declspec(dllexport) #include <iostream> using namespace std; //注意这里的extern "C" , 这里必须加 extern "C" DLL_API int add(int a,int b) //实现两个整数相加 { return a+b; } extern "C" DLL_API int subtract(int a,int b) //实现两个整数相减 { return a-b; } #include <iostream> #include <Windows.h> using namespace std ; typedef int (*func)(int x , int y); //函数指针 int main() { HINSTANCE hInstance = LoadLibrary("DLL.dll"); if(hInstance == NULL) { cout << "SB" << endl ; return 0; } func add = (func)GetProcAddress(hInstance, "add"); func sub = (func)GetProcAddress(hInstance, "subtract"); cout << (*add)(3,4) << endl ; cout << (*sub)(5,3) << endl ; }

    显然,这种方法没有用lib文件方便,如果为了每次调用一个函数还要自己再弄一个函数指针,多麻烦啊,所以,我们在实际开发中,用的众多的第三方扩展库,别人都是提供的:

    .h 文件(类,函数的声明)

    .dll 文件(类或函数的实现)

    .lib 文件(导入库)

    3. Linux下静态库、动态库的创建与使用

    Linux下静态库、动态库的创建与使用

    4. QT下静态库、动态库及Plugin的创建与使用

    4.1 QT下静态库的创建与使用

    4.1.1 创建静态库

    新建项目Library|C++库,选择静态链接库 //staticlib.h #ifndef STATICLIB_H #define STATICLIB_H class StaticLib { public: StaticLib(); }; #endif // STATICLIB_H //staticlib.cpp #include "staticlib.h" #include <QDebug> StaticLib::StaticLib() { qDebug()<<"StaticLib success"; } 构建生成libstaticLib.a、staticlib.o

    4.1.2 使用静态库

    新建项目Application|Qt Console Application,将staticlib.h拷贝至项目根目录项目右键添加库,选择外部库libstaticLib.a #include <QCoreApplication> #include "staticlib.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); StaticLib lib; return a.exec(); }

    4.2 QT下动态库的创建与使用

    4.2.1 创建动态库

    新建项目Library|C++库,选择共享库 //sharelib.h #ifndef SHARELIB_H #define SHARELIB_H #include "sharelib_global.h" class SHARELIBSHARED_EXPORT ShareLib { public: ShareLib(); }; #endif // SHARELIB_H //sharelib.cpp #include "sharelib.h" #include <QDebug> ShareLib::ShareLib() { qDebug()<<"ShareLib success"; } 构建生成libshareLib.a、shareLib.dll、sharelib.o

    4.2.2 使用动态库

    新建项目Application|Qt Console Application,将shareLib.h、libshareLib.a拷贝至项目根目录将shareLib.dll拷贝至项目工作目录项目右键添加库,选择外部库libstaticLib.a #include <QCoreApplication> #include "staticlib.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); StaticLib lib; return a.exec(); }

    4.3 QT下Plugin的创建与使用

    4.3.1 高级插件

    参考文档

    使用插件扩展Qt自身

    使用示例代码styleplugin

    修改simplestyle.cpp

    #include <QtWidgets> #include "simplestyle.h" void SimpleStyle::polish(QPalette &palette) { // palette.setBrush(QPalette::Button, Qt::red); palette = QPalette(QPalette::Button, Qt::blue); } 将生成的于debug\styles下的simplestyleplugin.dll拷贝至mingw73_32\plugins\styles使用QApplication::setStyle(QStyleFactory::create("simplestyle"));可调用样式插件

    4.3.2 底层插件

    参考文档 Qt插件创建及加载

    4.3.2.1 项目环境搭建

    新建项目其他项目|子目录项目,MyPlugin创建子项目Application|Qt Console Application,MainWidget 功能:完成主界面绘制,插件接口的定义和调用 创建子项目Application|Qt Console Application,PluginWidget 功能:完成插件接口的实现

    4.3.2.2 定义插件接口

    在项目MainWidget,创建头文件abstractinterface.h #ifndef ABSTRACTINTERFACE_H #define ABSTRACTINTERFACE_H #include <QObject> class QWidget; class AbstractInterface { public: virtual ~AbstractInterface() {} virtual QWidget *createPluginWidget(QWidget *parent) = 0; }; #define AbstractInterface_iid "namehao465" Q_DECLARE_INTERFACE(AbstractInterface, AbstractInterface_iid) #endif // ABSTRACTINTERFACE_H

    4.3.2.2 实现插件定义

    修改PluginWidget.pro文件 ...... TEMPLATE = lib CONFIG += plugin ...... INCLUDEPATH += ../MainWidget 设计pluginwidget.ui添加控件新建MyFirstPlugin类 //MyFirstPlugin.h #ifndef MYFIRSTPLUGIN_H #define MYFIRSTPLUGIN_H #include <QObject> #include "pluginwidget.h" #include "abstractinterface.h" class MyFirstPlugin : public QObject,public AbstractInterface { Q_OBJECT public: explicit MyFirstPlugin(QObject *parent = nullptr); Q_INTERFACES(AbstractInterface) Q_PLUGIN_METADATA(IID "namehao465" FILE "myfirstplugin.json") QWidget* createPluginWidget(QWidget *parent); signals: public slots: }; #endif // MYFIRSTPLUGIN_H //MyFirstPlugin.cpp #include "myfirstplugin.h" MyFirstPlugin::MyFirstPlugin(QObject *parent) : QObject(parent) { } QWidget *MyFirstPlugin::createPluginWidget(QWidget *parent) { PluginWidget *pluginWidget = new PluginWidget(parent); return pluginWidget; } 构建PluginWidget项目生成PluginWidget.dll

    4.3.2.3 实现插件调用

    将PluginWidget.dll拷贝至build-MyFirstPlugin-Desktop_Qt_5_12_2_MinGW_32_bit-Debug\MainWidget修改widget.ui添加QWidget控件widget2修改widget类实现插件的查找调用 //Widget.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "abstractinterface.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; bool loadPlugin(); AbstractInterface* m_pluginInterface; }; #endif // WIDGET_H //Widget.cpp #include "widget.h" #include "ui_widget.h" #include <QDir> #include <QPluginLoader> #include <QApplication> #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); loadPlugin(); } Widget::~Widget() { delete ui; } bool Widget::loadPlugin() { QDir pluginsDir; bool ok = false; foreach(QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName)); QObject *plugin = pluginLoader.instance(); if(plugin){ qDebug()<<pluginsDir.absoluteFilePath(fileName); m_pluginInterface = qobject_cast<AbstractInterface *>(plugin); if(m_pluginInterface){ m_pluginInterface->createPluginWidget(ui->widget2); ok = true; } } } return ok; } 运行MainWidget实现插件调用
    Processed: 0.021, SQL: 9