写了一个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,不仅起不到好的作用,反而让代码更麻烦了。