具体程序如下:(贴得都是修改后得,用的是回调得方式获取到数据)
封装DLL库:需要注意: pro文件中不能包含任何Qt得库
然后修改文件global文件
#ifndef EAGLE_RF_NOVASKY_Q5M_GLOBAL_H
#define EAGLE_RF_NOVASKY_Q5M_GLOBAL_H
#if defined(EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT)
# define EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT __declspec(dllexport)
#else
# define EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT __declspec(dllimport)
#endif
#endif // EAGLE_RF_NOVASKY_Q5M_GLOBAL_H
h文件(对外得h文件,需要注意内外函数得对应)
#ifndef EAGLE_RF_NOVASKY_Q5M_H
#define EAGLE_RF_NOVASKY_Q5M_H
#include "eagle_rf_novasky_q5m_global.h"
#ifdef __cplusplus
extern "C" {
#endif
// 不透明句柄
typedef void* eagle_rf_handle_t;
// 创建 / 销毁
EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT eagle_rf_handle_t eagle_rf_create(void);
EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT void eagle_rf_destroy(eagle_rf_handle_t h);
// 连接设备,成功返回 1,失败返回 0
EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT int eagle_rf_init(eagle_rf_handle_t h,
const char* ip,
int port);
// 断开设备
EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT void eagle_rf_deinit(eagle_rf_handle_t h);
// 收到数据解析后返回json
typedef void (*eagle_rf_json_cb)(void* user_data, const char* json);
typedef struct {
eagle_rf_json_cb on_json; // 每帧一个 JSON
void* user_data; // 原样回传
} eagle_rf_callbacks_t;
EAGLE_RF_NOVASKY_Q5MSHARED_EXPORT void eagle_rf_set_callbacks(
eagle_rf_handle_t h, const eagle_rf_callbacks_t* cbs);
#ifdef __cplusplus
}
#endif
#endif // EAGLE_RF_NOVASKY_Q5M_H
cpp文件
#define EAGLE_RF_NOVASKY_Q5M_LIBRARY
#include "eagle_rf_novasky_q5m.h"
#include "eagle_rf_novasky_q5m_impl.h"
#include <new>
extern "C" eagle_rf_handle_t eagle_rf_create()
{
return new (std::nothrow) Eagle_rf_novasky_q5m();
}
extern "C" void eagle_rf_destroy(eagle_rf_handle_t h)
{
delete static_cast<Eagle_rf_novasky_q5m*>(h);
}
extern "C" int eagle_rf_init(eagle_rf_handle_t h, const char *ip, int port)
{
if (!h || !ip) return 0;
return static_cast<Eagle_rf_novasky_q5m*>(h)->init(std::string(ip), port) ? 1 : 0;
}
extern "C" void eagle_rf_deinit(eagle_rf_handle_t h)
{
if (h) static_cast<Eagle_rf_novasky_q5m*>(h)->deinit();
}
extern "C" void eagle_rf_set_callbacks(eagle_rf_handle_t h, const eagle_rf_callbacks_t *cbs)
{
if (!h || !cbs) return;
static_cast<Eagle_rf_novasky_q5m*>(h)->setCallbacks(*cbs);
}
h文件(内部实现函数得文件)
#ifndef EAGLE_RF_NOVASKY_Q5M_IMPL_H
#define EAGLE_RF_NOVASKY_Q5M_IMPL_H
#include "eagle_rf_novasky_q5m.h"
#include <string>
#include <mutex>
class Eagle_rf_novasky_q5m
{
public:
Eagle_rf_novasky_q5m();
~Eagle_rf_novasky_q5m();
///
/// \brief init 连接设备
/// \param ip 设备ip地址
/// \param port 设备端口号
/// \return true-连接成功 false-连接失败
///
bool init(std::string ip, int port);
///
/// \brief deinit 断连设备
///
void deinit();
// 回调注册
void setCallbacks(const eagle_rf_callbacks_t& cbs);
private:
eagle_rf_callbacks_t m_cbs{};
mutable std::mutex m_cbMutex;
};
#endif // EAGLE_RF_NOVASKY_Q5M_IMPL_H
cpp文件
#include "eagle_rf_novasky_q5m_impl.h"
Eagle_rf_novasky_q5m::Eagle_rf_novasky_q5m()
{
}
Eagle_rf_novasky_q5m::~Eagle_rf_novasky_q5m()
{
}
bool Eagle_rf_novasky_q5m::init(std::string ip, int port)
{
return true;
}
void Eagle_rf_novasky_q5m::deinit()
{
}
void Eagle_rf_novasky_q5m::setCallbacks(const eagle_rf_callbacks_t &cbs)
{
std::lock_guard<std::mutex> lock(m_cbMutex);
m_cbs = cbs;
}
具体使用方法:需要将生成得dll文件放到生成得执行文件同级目录中
h文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "eagle_rf_novasky_q5m.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
// 主线程槽:接收 DLL 推来的 JSON
void onJsonFrame(const QString& json);
void on_pushButton_1_clicked();
private:
Ui::Widget *ui;
// 静态回调,签名必须和 detect_rf_json_cb 一致
static void cbJson(void* user_data, const char* json);
eagle_rf_handle_t m_handle;
bool m_connect;
};
#endif // WIDGET_H
cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <QMetaObject>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_connect = false;
// 创建 DLL 内部对象
m_handle = eagle_rf_create();
if (!m_handle) {
qDebug() << "eagle_rf_create failed";
}
// 注册回调
eagle_rf_callbacks_t cbs{};
cbs.on_json = &Widget::cbJson; // 函数指针
cbs.user_data = this; // 把 this 传给回调
eagle_rf_set_callbacks(m_handle, &cbs);
}
Widget::~Widget()
{
if (m_handle) {
// 先清掉回调,避免 DLL 析构过程中还有数据回调到已销毁的 Widget
eagle_rf_callbacks_t empty{};
eagle_rf_set_callbacks(m_handle, &empty);
eagle_rf_deinit(m_handle);
eagle_rf_destroy(m_handle);
m_handle = nullptr;
}
delete ui;
}
void Widget::onJsonFrame(const QString &json)
{
QJsonParseError err{};
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8(), &err);
if (err.error != QJsonParseError::NoError || !doc.isObject()) {
qDebug() << "json parse error:" << err.errorString() << json;
return;
}
qDebug()<<json;
}
void Widget::cbJson(void *user_data, const char *json)
{
Widget* self = static_cast<Widget*>(user_data);
if (!self || !json) return;
// 立即拷贝成 QString(json 指针在回调返回后失效)
QString s = QString::fromUtf8(json);
// 切回主线程,异步调用 onJsonFrame
QMetaObject::invokeMethod(self, "onJsonFrame", Qt::QueuedConnection,
Q_ARG(QString, s));
}
void Widget::on_pushButton_1_clicked()
{
static int m_click = 0;
if (!m_handle) {
qDebug() << "handle is null";
return;
}
if (((m_click++) % 2) == 0) {
// ---- 连接 ----
QString ip = ui->lineEdit_1->text().trimmed();
int port = ui->lineEdit_2->text().toInt();
int ok = eagle_rf_init(m_handle, ip.toUtf8().constData(), port);
m_connect = (ok != 0);
qDebug() << "init result:" << m_connect;
if (m_connect) {
ui->pushButton_1->setText(QStringLiteral("关闭"));
} else {
ui->pushButton_1->setText(QStringLiteral("开启"));
}
} else {
// ---- 断开 ----
eagle_rf_deinit(m_handle);
m_connect = false;
ui->pushButton_1->setText(QStringLiteral("开启"));
}
}
执行文件界面
