Qt插件使用学习笔记PART2

原创 2015年07月07日 14:15:07

用另一种方式实现Qt的插件制作与使用,这种方式的想法是这样的:

AbstractDevice(即两个device的父类)被做成一个动态链接库,用包含头文件与在工程文件中定义LIBS关键字来把其做成user_interface与两个device都可以使用的动态链接库,注意是动态链接库,不是插件。在具体细节实施之前,我了解到了几个重要信息:

1. interface也可以定义成一个类里并不全是纯虚函数,比如我这个例子里用Qt的宏把AbstractDevice这个类定义成了一个interface。

2.根据MSDN的 Dynamic-Link library的一个介绍文档:

https://msdn.microsoft.com/en-us/library/ms682586(v=vs.85).aspx#standard_search_order_for_desktop_applications

  • If a DLL with the same module name is already loaded in memory, the system uses the loaded DLL, no matter which directory it is in. The system does not search for the DLL.
  • If the DLL is on the list of known DLLs for the version of Windows on which the application is running, the system uses its copy of the known DLL (and the known DLL's dependent DLLs, if any). The system does not search for the DLL. For a list of known DLLs on the current system, see the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.

根据windows查找的顺序,动态库一般是要放在可执行文件的所在的目录下的,当动态库已经被加载了(应该是根据动态库文件名判断),不会反复加载。例如我在运行可执行文件时加载了动态库,当插件还是需要加载同一个动态库的时候,不会重新加载。

下面图片是我工程的一个大概介绍:


user_interface这个子项目只进行了很小的修改,因为我重新定义了device的interface。项目中,AbstractDevice是一个动态库,而FLOODCONTROL和PRECHARGE是我所制作的插件。下面开始上代码

abstract_device.pro:

QT       -= gui
QT+= core serialport


TARGET = abstract_device
TEMPLATE = lib

DEFINES += ABSTRACT_DEVICE_LIBRARY

SOURCES += abstract_device.cpp

HEADERS += abstract_device.h\
        abstract_device_global.h
INCLUDEPATH  += ../../user_interface

DESTDIR       = ../../plugins
可以看到我没有定义CONFIG为plugin。

abstract_device.h:

#ifndef DEVICE
#define DEVICE
#include <QObject>
#include <QTimer>
#include <QByteArray>
#include <QString>
#include <QSerialPort>
#include <QByteArray>
//#include "device_interface.h"
#include "global.h"
#include "abstract_device_global.h"

class ABSTRACT_DEVICESHARED_EXPORT AbstractDevice:public QObject
{

    Q_OBJECT
public:


    explicit AbstractDevice(QObject *parent=0);
  //  bool getPortDiscon();
   virtual void sendData(double info, sendCommands command)=0;
    bool isOpen();
    virtual void sendReset()=0;
     void closePort();
    void openPort(QString port_name);
    double getCvVal();
    double getFcVal();
    double getEcVal();
    double getFvVal();
    void setCvVal(double value);
    void setFcVal(double value);
    void setEcVal(double value);
    void setFvVal(double value);
  //  void flushPort();
    virtual void getVersion()=0;
    deviceState currentState();


signals:
    void sendInfo(double value, readCommands command);
    void sendMessage(double value,  sendCommands command);
    void sendConnectionError();
    void versionInfo(int ver_1 ,int ver_2);
    void needReset();
    void commandError();
    void stateSignal(deviceState state);

public slots:
    virtual void sensorDisplay()=0;
   //  void checkConnection();
      void connectionError();
     // void checkConnection2();


   // void closingPort();
protected:
      QSerialPort *port;
      deviceState state;
      QTimer* connect_timer;


private:
    QTimer* second_connect_timer;


    double cvVal;
    double fcVal;
    double ecVal;
    double fvVal;
};
Q_DECLARE_INTERFACE(AbstractDevice, "deviceinterface")
#endif // DEVICE
这里我用了Qt的宏来把interface declare 了。在abstract_device_global.h里定义的宏ABSTRACT_DEVICE_EXPORT也用在了这里,源文件是毫无变化的。

我用这个代码生成了一个动态库,在user_interface项目里的可执行文件要加载这个动态库,然后我的两个插件也要加载这个动态库,由上面粘贴的msdn的信息可得知我的动态库被exe文件加载了,插件就不会去重新加载了。


floodcontrol.pro:

QT       -= gui
QT   +=core serialport
TARGET = floodcontrol
TEMPLATE = lib
CONFIG +=plugin

DEFINES += FLOODCONTROL_LIBRARY

SOURCES += floodcontrol.cpp

HEADERS += floodcontrol.h\

INCLUDEPATH  += ../../user_interface\
                ../abstract_device

win32-g++*:LIBS+= D:\voltage_controller_redo_out\plugins\libabstract_device.a
#win32-msvc*:LIBS+= D:\msvc_out\plugins\abstract_device.lib
#LIBS += -LD:\msvc_out\plugins -labstract_device

DESTDIR       = ../../plugins

这里我把项目的链接库用LIBS关键字定义了,CONFIG定义成了PLUGIN。

floodcontrol.cpp:

#ifndef FLOODCONTROL_H
#define FLOODCONTROL_H

#include "abstract_device.h"
#include <QList>
#include <QQueue>
#include <QVector>
#include <QFile>

class FloodControl: public AbstractDevice
{
    Q_OBJECT
    Q_INTERFACES( AbstractDevice )
      Q_PLUGIN_METADATA(IID "deviceinterface")


public:


    explicit FloodControl(QObject *parent=0);
    void sendData(double info, sendCommands command);
    void sendReset();
    void getVersion();
    QString deviceName();

    //void sendReset();
   // void getVersion();
signals:

   // void sendConnectionError();
   // void versionInfo(int ver_1,int ver_2);


public slots:

  //  void checkConnection();
   // void connectionError();
    void sensorDisplay();
    void autoSend();
   //void sensorDisplay();
  //  void checkConnection();
  //  void connectionError();

private:



   //   QTimer *connect_timer;
    //    int buffer_pos;
    QQueue<QString> commandBuffer;
    QVector<QString> normalCommands;

    bool sendFlag;
    QTimer *sendTimer;
    int normalComPosition;
    QTimer *autoTimer;
     QTimer *connect_timer;
     QByteArray comm;
     QFile *file;

};

#endif // FLOODCONTROL_H

这个是插件的制作所需要的宏,运行在宏Q_OBJECT之后。

在user_interface项目中我也运用了定义链接库,包含头文件的方式来构建项目。值得注意的是,动态链接库文件和可执行文件(.exe)放在同一个目录下,对新手来说很方便,不用考虑查找顺序和方式带来的加载问题。

Qt插件使用的学习笔记

之前做了一个电压箱控制界面程序,这个界面程序需要用作控制两个不同型号的电压箱,之前的做法是写出两个设备类,然后每次让用户选择生成某一个设备的对象,然后进行操作。这次的做法是把两个设备写成插件形式,在程...
  • chengsida111
  • chengsida111
  • 2015年07月03日 08:56
  • 984

qt 创建插件和使用

首先,创建一个插件 接着我们需要增加一个C++头文件声明接口,regexpinterface.h代码如下: #ifndef REGEXPINTERFACE_H #define REGEXP...
  • cqltbe131421
  • cqltbe131421
  • 2017年09月20日 13:48
  • 140

QT静态库使用插件的小TIP

本来想在QT下使用ODBC的plugin,但是发现编译生成的qsqlodbc.lib无法在plugin文件夹中载入,网上google了下,找到了答案,需要在源文件中加入如下声明:   //...
  • davidsu33
  • davidsu33
  • 2014年10月08日 09:17
  • 670

Qt学习笔记(一)

1、在Qt Creator中创建项目,当工程更改之后,要注意经常qmake以保持最新状态。...
  • skc361
  • skc361
  • 2013年10月14日 23:15
  • 1714

qt学习笔记001 2015/6/15

一、 QT入门1.图形化用户界面 (1)GUI -Graphical User Interface (2)Hello Qt #include #include int main(int a...
  • liquanquan19950628
  • liquanquan19950628
  • 2015年06月15日 16:25
  • 276

qt学习笔记(七)之数据库简介

笔者最近用Qt写公司的考勤机。本来要求是要基于frameBuffer下用自己开发的easyGUI来进行上层应用开发,但是考虑到easyGUI提供的接口不是很多,就考虑用Qt来开发,顺带练练手。 废话不...
  • liuligui5200
  • liuligui5200
  • 2015年07月09日 15:59
  • 361

基于6410的qt广告机移植小记

请按以下具体步骤操作: 1、确定需要有的几个文件:    a)、 qtopia-core-opensource-src-2.1.1.tar.gz   Qtopia库源码包    b)、交叉编译器...
  • ZYBASJJ
  • ZYBASJJ
  • 2012年05月17日 13:38
  • 2128

Embedding Python in Objective-C: Part 2

Embedding Python in Objective-C: Part 2 Virgil Dupras 2012-01-20 Two years ago, I wrote about h...
  • yuanya
  • yuanya
  • 2013年04月20日 15:09
  • 1217

自定义callouts part 2

前一篇是part1, part2在自定义的view上加了一些uiimageview与uibutton.请看原文。 Part 1 showed how to build a custom map cal...
  • favormm
  • favormm
  • 2011年02月14日 13:47
  • 2026

和菜鸟一起学OK6410之交叉编译hello world

看着大三买来的那块arm11(OK6410),又要开始冲动一把了,记得过年回来的时候,在ubuntu下搭建过OK6410的开发环境,不过不小心把ubuntu系统给卸载了,那软件还装了好多好多的,各种设...
  • eastmoon502136
  • eastmoon502136
  • 2012年06月29日 00:08
  • 3969
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Qt插件使用学习笔记PART2
举报原因:
原因补充:

(最多只允许输入30个字)