qt的dll内无法收到串口发来的读取信号

写了一个dll,主要问题是,其他程序调用我写的dll,首先先调用了open_port打开某个串口,并且把信号和槽函数连接,然后dll内应该是会根据这个信号不断来触发这个槽函数,但是一次也没触发,是什么原因,请大家看看!我需要的是别的程序打开我dll里的串口后,我的dll会一直根据这个信号来监听读取数据,但是信号一直没触发。

//dll的头文件 
#ifndef TEST_H
#define TEST_H

extern "C" __declspec(dllexport) void open_port();

extern "C" __declspec(dllexport) char* read();

#endif // TEST_H


//dll的cpp文件
#include "test.h"
#include "porttest.h"

static PortTest *test;

extern "C" __declspec(dllexport) void open_port(){

    test=new PortTest();
}

extern "C" __declspec(dllexport) char* read(){

    char *buf=test->data.data();
    return buf;
}


//槽函数的头文件
#ifndef PORTTEST_H
#define PORTTEST_H

#include 
#include 
#include 

class PortTest : public QObject
{
    Q_OBJECT
public:
    explicit PortTest(QObject *parent = nullptr);
    QSerialPort *serial;
    QByteArray data;

public slots:
    void readData();
};

#endif // PORTTEST_H


//槽函数的cpp文件
#include "porttest.h"
#include 

PortTest::PortTest(QObject *parent) : QObject(parent)
{

    serial = new QSerialPort("COM4");
    serial->setBaudRate(QSerialPort::Baud9600);
    serial->setParity(QSerialPort::NoParity);
    serial->setDataBits(QSerialPort::Data8);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
    serial->open(QIODevice::ReadWrite);

    connect(serial,&QSerialPort::readyRead,this,&PortTest::readData);

}

void PortTest::readData()
{
    std::cout<<"触发槽函数了"<readAll();
}


你是QT新手还是熟手?

把open()挪到connect()之后

PortTest::PortTest(QObject *parent) : QObject(parent)
{
 
    serial = new QSerialPort("COM4");
    serial->setBaudRate(QSerialPort::Baud9600);
    serial->setParity(QSerialPort::NoParity);
    serial->setDataBits(QSerialPort::Data8);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);
   
    connect(serial,&QSerialPort::readyRead,this,&PortTest::readData);
 
    serial->open(QIODevice::ReadWrite);
 }
serial = new QSerialPort("COM4");

你的电脑是com4串口吗?建议先通过查找看一下串口号,确定后再调试。

  QList<QSerialPortInfo> list;
 
    list = QSerialPortInfo::availablePorts();
    for (int i = 0; i < list.size(); i++)
    {
         qDebug() << list.at(i).portName() ;//串口名字
         qDebug() << list.at(i).description();//串口描述
         qDebug() << "#########";
    }

你的设备是否已经成功连接了呢,如果连接都没有成功,是不可能触发这个信号的

(1)你的信号是绑定在PortTest 类的readData上的,所以,信号只会发到这个槽函数上,你在cpp中声明了一个静态全局变量test,但是这个test的作用域只在dll的cpp文件里,在你调用程序里是不认识这个变量的。所以你的代码是有问题的。

把你的dll的cpp文件改成下面的试一下:



//dll的cpp文件
#include "test.h"
#include "porttest.h"

//static PortTest *test;  //注释掉这一句

extern "C" __declspec(dllexport) PortTest * open_port(){  //把new的对象指针返回

    test=new PortTest();
    return test;
}

extern "C" __declspec(dllexport) char* read(PortTest *test){ //在这里通过对象指针获取数据

    char *buf=test->data.data();
    return buf;
}

(2)还有就是,你这么封装后怎么用的接口?你槽函数虽然能在收到信号的时候自动调用,但是,你封装的接口需要你在一个循环中不停的调用才行,而且需要你自己判断数据是否有更新,信号槽机制完全没用了。这个库封装的没有任何意义,反而让程序更加复杂(本来一个信号槽机制就能实现的问题,你这样封装后,反而需要自己用while循环不停的接收,并需要自己判断数据是否有更新)。按照这个思路封装后,调用接口的逻辑大体上是下面的样子:

PortTest *test = open_port(); //调用接口获取对象指针

//获取数据
/*因为信号槽机制限制在了test对象内部,而read()接口返回的是成员变量的值,这个成员变量的值在没有接收到新数据时是不会更新的,所以通过read()接口获取数据的时候,需要用while不停的获取数据,并且需要自己写代码判断数据是否有变化,以便知道串口是否发送了新的数据*/
char pre[1024]={0};  //申请一块内存,保存上一次接收到的数据
while(1)
{
    char* data = read(test);  //1.调用接口读取数据
    //判断数据是否有更新
    if(strcmp(pre,data) != 0) //说明数据有更新
    {
        //保存数据,以便下一次进行比较
        strcpy(pre,data);
        //有更新的时候再去处理数据
    }
}

最后,真的不建议你这么封装dll,不仅起不到好的作用,反而让代码更麻烦了。