利用回调函数实现DLL与Qt主程序的数据交互,进一步实现对Qt主程序中的信号触发

您所在的位置:网站首页 qt数据交互 利用回调函数实现DLL与Qt主程序的数据交互,进一步实现对Qt主程序中的信号触发

利用回调函数实现DLL与Qt主程序的数据交互,进一步实现对Qt主程序中的信号触发

2024-07-17 21:32:36| 来源: 网络整理| 查看: 265

Qt并没有提供串口通讯的接口,为了实现Qt程序的串口通讯,多数开发者都采用了一个第三方接口win_qextserialport。这个接口是完全基于Qt类库的,很容易就可以把它加载到自己的程序里边。但在实际应用过程中,发现了一个奇怪的现象:

我的上位机程序是要通过控制串口(USB转的)来实现与下位机的通讯,经过测试,在相同的设置下,上位机程序和串口调试软件能够正常通讯,下位机和串口调试软件也能够正常通讯。按理说,这个时候上下位机也就应该能够正常地通讯了,但事实却很残酷:它们无法沟通,下位机接不到上位机的数据,上位机也接不到下位机的数据,----无论我如何调节相关设置、重新开关机,都无济于事。

我不知道win_qextserialport到底怎么了,实在无暇去深究。因为时间比较紧,我不得不尽早尝试新的串口通讯接口。

最直接的就是调用Windows API了,但那一堆堆冗长的接口函数实在繁琐。幸运的是有个大牛发布了一个C++串口通讯程序接口(CnComm.h头文件源代码,最新版是1.5),非常方便。因为它需要在VC下编译,所以我必须把它打包成DLL然后提供给Qt主程序调用。到这里,我面临很多的问题:

1 大牛的接口是C++的,Qt可以容易地实现对DLL里的函数的调用,但如何调用Dll里的类?

2 我需要在串口接收到数据后,把数据传回主程序,并马上在Qt主程序里释放一个信号(signal),以通知主程序处理。如何实现?

3 DLL里根本不知道Qt主程序里的相关的类,更不知道Qt中的emit为何物,怎么传递Qt主程序里的类给他?

 

最后是通过回调函数来实现的。

回调函数,就是把一个函数A的指针传递给另一个函数B,由函数B再调用函数A,这样就可以实现模块间的交互操作。如果再把函数A的指针传递给函数B的同时,也把相关的参数一起传递给函数B,那么就可以实现模块间的数据交互。

例如:

int sumit(int x, int y){    return x + y ;}

void testit(int a, int b, int (*func)(int, int)){    QString strs = QString::number(func(a,b));    qDebug(strs.toAscii());}

 

可以这样调用: testit(1,2,sumit);打印输出值:3

 

下面是DLL与Qt主程序的主要实现代码:

1 DLL代码

#include "CnComm.h"class communicate;                                          //Qt中类的前向声明,通知DLL这是一个类typedef void(*Emit)(communicate*, char*, int);     //函数指针类型定义

class HRComm : public CnComm   {   private:     Emit emitSignal ;             //信号释放函数的指针, 用于指向回调函数     communicate * pComm;   //Qt中类实例的指针,指向Qt主程序中的类实例,作回调函数的实参,以便在Qt主程序中进行信号释放

     char *pDataBuffer;           //接收数据缓存指针     int  iLength;                    //接收到的字节数     void OnReceive()             //重载接收函数    {         int dataLen = Read(pDataBuffer, iLength);   //读取串口数据,返回实际接收的数据字节数         emitSignal(pComm,pDataBuffer,dataLen);   //回调在此发生!传数据到到Qt主程序中,并把释放信号的类实例指针回传。    }

public:     void SetSignal(communicate*  commn, char *pData, int len, Emit func);  //设置类参数, 把Qt主程序里的函数指针和其参数传到该串口通讯类中};

 

void HRComm::SetSignal(communicate *commn, char *pData, int len,  Emit func){     pDataBuffer = pData;   

     iLength = len;                  emitSignal = func;       //传递Qt主程序里的函数(回调函数)指针     pComm = commn;      //传递Qt主程序里的类实例指针}

 

HRComm hrComm;     //实例化一个串口通讯类

 

bool openPort(int port, int baudrate)  {    return hrComm.Open(port, baudrate);}

void closePort(void){       hrComm.Close();}

void sendData(char *buff, int len){      hrComm.Write(buff, len);}

void setReceiveSignal( communicate *commn,char *pData, int len,  Emit pFunc)   {     hrComm.SetSignal(commn, pData, len, pFunc);}

 

Qt主程序通过调用openPort、closePort、sendData和setReceiveSignal分别实现打开串口、关闭串口、发送数据和回调函数传递。

 

2 Qt 主程序主要实现代码

 1)communicate.h

 #ifndef COMMUNICATE_H#define COMMUNICATE_H#include "win_qextserialport.h"#include

class Signal;class QString;class QByteArray;class QLibrary; 

class communicate: public QObject{    Q_OBJECTpublic:    QLibrary  *lib;    int iDataLen;    char *pData;

    communicate(QWidget *parent = 0);    Win_QextSerialPort *myCom;    int iPortNumber;    void Connect(void);

    bool b_checked;    void Open(int portNumber);    bool TestPort(int portNumber);    void SetSignalEmit(char *data, int len);

signals:    void signalData(char *pData, int len);public slots:    void Close(void);    void GotData(char *pData, int len);

};

#endif // COMMUNICATE_H

 

 2)communicate.cpp

#include "communicate.h"#include "data.h"#include #include typedef bool(*OpenPort)(int, int);typedef void(*ClosePort)(void);typedef void(*SendData)(char*, int);typedef void(*SetSignal)(communicate*, char*, int, void(*pf)(communicate*, char*, int));

 //回调函数。C++中,类成员函数不可以作回调函数,要不然就不用这么麻烦把communicate *comm传来传去了。void SetIt(communicate *comm, char *data, int len) {    qDebug("GOT DATA!");    QByteArray * bytes = new QByteArray;    for (int i=0; iappend(*(data+i));    qDebug(bytes->toHex());    comm->SetSignalEmit(data, len);    comm->b_checked = true;}

 

void communicate::Connect(void){    connect(myCom, SIGNAL(readyRead()),this,SLOT(readCom()));}

communicate::communicate(QWidget *parent){    b_checked = false;    strpc  = SUNG_ID_CODE; 

    iDataLen = 1024;    pData = new char[1024];

    lib = new QLibrary("CommuModual.dll");    if(lib->load())    {        qDebug("dll is loaded");    }    else        qDebug("dll loading failed.");

    connect(this, SIGNAL(signalData(char*,int)),this, SLOT(GotData(char*,int)));

}

void communicate::GotData(char*,int){

    b_checked = true;}

 

void communicate::SetSignalEmit(char *data, int len){    emit this->signalData(data, len);}

void communicate::Open(int portNumber){    OpenPort openPort = (OpenPort)lib->resolve("openPort");    if (openPort)    {        qDebug("openPort loaded");        if(openPort(portNumber,115200))            qDebug("port opened");        else            qDebug("port opening failed.");    }    else        qDebug("openPort loading failed");

}

bool communicate::TestPort(int portNumber){    iPortNumber = portNumber;    SetSignal setSignal = (SetSignal)lib->resolve("setReceiveSignal");    if (setSignal)    {        qDebug("SetReceiveSignal loaded");        setSignal(this,this->pData, this->iDataLen,SetIt); //设置信号与回传        qDebug("Signal is set");    }

    Open(portNumber); //打开串口    SendData sendData = (SendData)lib->resolve("sendData");    if (sendData)    {        qDebug("sendData loaded");        QString strtemp = SUNG_ID_CODE;        int len = strtemp.count();        char *dt = new char[len+3];        *dt = 0xFF;        *(dt+1) = INST_ID_CODE;        for (int i=0; i       qDebug("closePort loaded");       closePort();       qDebug("port is closed");   }   else       qDebug("closePort loading failed");

   delete lib;   lib = NULL;

}

 

3)main.cpp

#include "communicate.h"

void main(int argc, char *argv[]){

    communicate  commn;    commn.TestPort(13); //测试:打开串口13,设置回调函数、数据传输参数

    while(!commn.b_checked)        ;}



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭