• 1、Qt 插件开发方式


    插件类其实就是接口类的子类,用于实现接口类。

    该Interface必须是虚基类,且所有函数(除了析构)都是虚函数。

    而所谓的plugin就是继承该虚基类和QObject的子类。

    当程序调用该plugin的某个函数时,是通过该plugin的虚基类在运行时动态绑定至子类的vtable执行的。

    1、编写接口类

    创建项目 MyPlugin1,最终用于生成插件 MyPlugin1.dll

    个人习惯,勾选小写,其他全部默认

    最终项目中,多出一个*_global.h文件,此文件不需任何更改。

    添加接口类头文件 MyInterface.h

    MyInterface.h

    #pragma once
    #include <QObject>
    #include <opencv.hpp>
    /**
    * @brief 
    * 接口类格式:
    * 1、虚析构
    * 2、其他函数纯虚
    * 3、无成员变量
    */
    class MyInterface
    {
    public:    //公开
        virtual ~MyInterface(){}
        virtual void medianFilter(const cv::Mat& inputImg, cv::Mat& outputImg) = 0;
    };
    
    //声明接口
    #define MyInterface_IID "com.Interface.MyInterface"
    Q_DECLARE_INTERFACE(MyInterface,MyInterface_IID)

    2、实现接口类

    myplugin1.h

    #pragma once
    
    #include "myplugin1_global.h"
    #include "MyInterface.h"    //引入接口类
    
    /**
    * @brief
    * 插件类其实就是接口类的子类,用于实现接口类
    * 格式:
    * 1、继承QObject
    * 2、继承接口类
    */
    class MYPLUGIN1_EXPORT MyPlugin1
        :public QObject
        ,public MyInterface
    {
        //宏3联
        Q_OBJECT
        Q_PLUGIN_METADATA(IID MyInterface_IID)  //描述插件元数据
        Q_INTERFACES(MyInterface)               //本类要实现的接口
    public:
        MyPlugin1();
        ~MyPlugin1();
        //实现的虚函数
        virtual void medianFilter(const cv::Mat& inputImg, cv::Mat& outputImg) override;
    };

    myplugin1.cpp

    #include "myplugin1.h"
    
    MyPlugin1::MyPlugin1()
    {
    }
    MyPlugin1::~MyPlugin1()
    {
    }
    
    void MyPlugin1::medianFilter(const cv::Mat& inputImg, cv::Mat& outputImg)
    {
        cv::medianBlur(inputImg, outputImg, 5);
    }

    运行,会在Debug或Release中生成dll

    3、新建程序,PluginDemo

    在exe目录里新建plugins文件夹,把之前生成的插件dll放入其中。

    【注意】dll是区分编译器版本、debug/release的,exe需使用对应的dll。类似VS不能用MinGW编译的dll。

    把之前的接口文件放入项目路径,并添加到VS项目中

    运行结果

    main.cpp

    #include <QtCore/QCoreApplication>
    #include <QDir>
    #include <QPluginLoader>
    
    #include"MyInterface.h" //引入接口类
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        //加载插件
        QDir pluginsDir = QDir(qApp->applicationDirPath()); //exe路径
        if (!pluginsDir.cd("plugins"))                      //若无法进入plugins文件夹则返回
        {
            return -1;
        }
        int counter = 0;    //统计有效插件,无则返回
        for each (QString pluginName in pluginsDir.entryList(QDir::Files))   //遍历plugins中的插件(库)
        {
            if (QLibrary::isLibrary(pluginName))           //是否是库文件
            {
                QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(pluginName));    //加载插件
                if (qobject_cast<MyInterface*>(pluginLoader.instance()))    //是否与插件接口兼容
                {
                    //一些操作,如将插件展示到界面等
                    //由于只是讲解插件的基本知识,此段仅参考即可。可以直接指定具体的dll进行函数调用。
                    counter++;
                }
            }
        }
        if (0==counter)     //无有效插件则返回
        {
            return -1;
        }
        //直接指定具体的dll进行函数调用
        QPluginLoader pluginLoaderNow(qApp->applicationDirPath() + "/plugins/MyPlugin1.dll");   //加载插件
        MyInterface* plugin = qobject_cast<MyInterface*>(pluginLoaderNow.instance());           //实例化,接口类对象
        cv::Mat src, dst;
        src = cv::imread("C:/line.bmp");
        plugin->medianFilter(src, dst); //调用函数
        cv::imshow("原图", src);
        cv::imshow("插件里实现的中值滤波", dst);
    
        return a.exec();
    }
  • 相关阅读:
    java8学习笔记之lambda表达式
    spring注解value的用法
    mybites
    spring bean的初始化以及销毁
    java并发之线程间通信
    mybatis常见问题和错误
    hadoop安装问题记录
    linux 常用命令
    省选模拟98 题解
    省选模拟97 题解
  • 原文地址:https://www.cnblogs.com/xixixing/p/15927625.html
Copyright © 2020-2023  润新知