库的概述:qt插件(库)的使用

库的基本概念

0 库链接

说明:在不同平台下,库的表现形式是不一样的。

linux平台windows平台
动态库.so.dll
静态库.a.lib
目标文件.o.obj
其中 .a 是linux下经过一堆.o文件链接的集合,.lib是windows下一堆.obj经过链接的集合 

动态链接:共享dll(.so)的数据和代码。操作系统可以提供一种方式让进程可以调用不属于自身的代码和访问数据,动态库包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
静态链接:链接器从库复制所需的代码编译好的二进制数据,和代码的obj(linux下是.o文件)一起链接,生成exe(a.out)可执行文件。缺点是多次引用静态库,则会多次拷贝链接到exe/a.out内。

1 .dll .lib .obj

在windows操作系统下,经过vs编译为静态库和动态库都含有.lib文件,它们的区别是:
静态库中的lib:该LIB包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中

动态库中的lib:该LIB包含了函数所在的DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供

总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。在开发和调试阶段,当然最好都有。

2 .so .a .o

linux下文件的类型是不依赖于其后缀名的,但一般来讲:
.o,是目标文件,相当于windows中的.obj文件
.so 为共享库,是shared object,用于动态连接的,和dll差不多
.a为静态库,是好多个.o合在一起,用于静态连接
.la为libtool自动生成的一些共享库,vi编辑查看,主要记录了一些配置信息。可以用如下命令查看*.la文件的格式 $file *.la
*.la: ASCII English text
所以可以用vi来查看其内容。

qt插件的生成

1 在qt 下制作插件流程:
在这里插入图片描述
基类的实现:filterinterface.h

#include <cstdio>
#include <QDebug>
/*
 插件基类,所有插件继承自这个类
*/

class PluginInterFace
{
public:
    PluginInterFace()
    {
          printf("PluginInterFace构造了\n");
    }

    virtual ~PluginInterFace(){
        printf("PluginInterFace析构了\n");
    }
    virtual void SayHello() {}// 纯虚函数

};

// 定义动态库 iid (唯一的识别标识)
#define pluginInterFace_iid "io.qt.dynamicplugin"
// 向qt的元对象系统声明了这个插件接口
// 类名,类名iid
Q_DECLARE_INTERFACE(PluginInterFace, pluginInterFace_iid)

插件的实现:

#ifndef PLUGIN_H
#define PLUGIN_H

#include <QObject>
#include "../test1/filterinterface.h"
#include "hello.h"
// 构建的是 plugin子项目,而不是运行整个项目,会生成 .dll文件
class Plugin : public QObject, public PluginInterFace
{
    Q_OBJECT
    //  插件基类的iid 及 包含插件元数据的json文件【我们必须新建一个json文件,名称与这相同  json文件内容是{} 】
   	// 也可以不需要 json文件
    Q_PLUGIN_METADATA(IID pluginInterFace_iid FILE "plugin.json")
    // 基类名称
    Q_INTERFACES(PluginInterFace)
public:
    explicit Plugin(QObject *parent = nullptr);
    ~Plugin();

    void SayHello();

    Hello he;

signals:

public slots:
};

#endif // PLUGIN_H

配置插件项目的pro文件:(必须)

HEADERS += \
    plugin.h \
    hello.h

SOURCES += \
    plugin.cpp \
    hello.cpp

# 窗口模块
QT += core widgets
# 必须配置好,才是动态插件
# TEMPLATE 表示生成的目标是 app 还是 lib 等
TEMPLATE = lib
CONFIG += Plugin

DISTFILES += \
    plugin.json

最后是使用dll:
固定加载:

    PluginInterFace * interface = nullptr;
    QPluginLoader pluginLoader("plugin.dll");
    QObject *plugin = pluginLoader.instance();
    if(plugin)
    {
        interface = qobject_cast<PluginInterFace*>(plugin);
        if(interface)
        {
            interface->SayHello();
        }
    }

动态加载刷新dll:(案例)

// 通过获取 plugins/phones 目录下的所有dll,筛选需要加载的dll
ScreenTool *GetPhoneObject::phoneObject(const QString &iMenufest, const QString &iSerial)
{
    if(iSerial.isEmpty())
    {
        qDebug() << "iSerial is null";
        return NULL;
    }
    if(!pluginPath.isEmpty())
        pluginPath.clear();
    pluginPath.append(qApp->applicationDirPath());


    PhoneCreateManage *manage = NULL;
    QDir pluginDir(pluginPath);
//    pluginDir.cdUp();
    pluginDir.cd("plugins");
    pluginDir.cd("phones");
    const auto pluginList = pluginDir.entryList(QDir::Files);
    foreach (const QString &fileName , pluginList) {
        QPluginLoader loader(pluginDir.absoluteFilePath(fileName));//这里必须使用  pluginDir.absoluteFilePath(fileName)来转换fileName,否则会加载失败
        QObject *phone = loader.instance();
        qDebug() << "loader phone:" << loader.errorString() << " " <<fileName;
        myLog->writeLog("GetPhoneObject.cpp", 69, 4, 0, QString("loader phone: %1").arg(loader.errorString()).toStdString().c_str());
        if(phone)
        {
            manage = qobject_cast<PhoneCreateManage*>(phone);
            if(manage)
            {
                qDebug() << manage->serialId();
                if(manage->serialId() == iSerial.trimmed())
                {
                    ScreenTool * tool = manage->createPhone(manage->returnMenufest(), iSerial);
                    tool->setPhoneProduct(manage->returnProduct());
                    tool->setPhoneSize(manage->returnPhoneSize());
                    tool->setPhoneVersion(manage->returnPhoneVersion());

                    return tool;
                }

            }
        }
    }


    return NULL;
}

总结

在使用库的过程中遇到很多的坑,原因是我对库的概念不清晰。
qt使用插件:把插件编译成为realse | debug版本根据项目是什么版本编译的,版本不一样会出错
某些vs编译的lib静态库,只能在vs下使用,这是我遇到的坑之一

参考内容

dll和so文件区别与构成
“.dll .obj .lib”和“ .so .o .a”文件与动态链接和静态链接

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

love_0_love

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值