通过 Qt 中的线程调用 Rust 库

Calling a Rust libary through a thread in Qt

本文关键字:调用 Rust 线程 Qt 通过      更新时间:2023-10-16

我正在为 Rust 库制作一个 Qt 前端,它公开了一个 C++ 函数,该函数阻止它所在的执行线程,但允许传递回调函数用于两端之间的通信。

所以我想使用 Qt 的线程技术让库在另一个线程上执行,我想用尽可能少的修改来做 Rust 库

这是我使用 QThread 的方法:

后端.cpp:

typedef void(*callback_t)(void *,const char *);
extern "C" call_rust_library(const char *config, void *cb_data, callback_t cb);
template<typename T>
void call_wrapper(void *ptr, const char*data) {
(*static_cast<T*>(ptr))(data);
}
class BackEnd : public QObject {
Q_OBJECT
public slots:
void do_computations(ConfigObject *config) {
//...parse configuration from the frontend...
char* parsed_configuration;
BackEnd* backend = this;
auto callback = [backend](char* data) {
//...process obtained data from the library...
QString type,contents;
backend->emit send_message(type,contents);
}
call_rust_library(parsed_configuration,(void *)&callback,call_wrapper<decltype(callback)>);
}
signals:
void send_message(QString type, QString contents);
}

前端.cpp:

class FrontEnd : public QMainWindow {
Q_OBJECT
QThread thread;
ConfigObject *config;
public slots:
void process_message(QString type, QString contents) {
//...do GUI things with the message
}
private slots:
void on_request_start_thread() {
// called by a GUI event
BackEnd* backend = new BackEnd;
backend->moveToThread(&thread);
connect(&thread,&QThread::finished,backend,&QObject::deleteLater);
connect(this,&FrontEnd::run_thread,backend,&BackEnd::do_computations);
connect(backend,&BackEnd::send_message,frontend,&FrontEnd::process_message);
emit run_thread(config)
}
signals:
void run_thread(ConfigObject *config);
}

但是我对此有几个问题:

  • 首先,后端不会执行任何内容。如果我不将后端对象移动到另一个线程,它似乎确实运行了所有内容,但在系统库的某个地方崩溃(我最好的猜测是因为Qt禁止阻止GUI线程和/或处理来自另一个线程的GUI函数(。
  • Qt 如何能够中止 Rust 库执行线程?(通过关闭应用程序或用户单击按钮(Rust 库似乎没有公开任何停止执行的机制,所以我想知道我是否必须对库进行修改以公开一个函数来中止它正在执行的任何操作。

最近我发现了这个示例存储库,它允许将 Qt 与 Rust 库绑定,但似乎没有深入研究多线程,并且可能需要将我的项目从 CMake 移植到 qmake。但是根据我的理解,Rust 执行应该驻留在另一个线程中,所以我不确定它是如何在这里实现的。

实现是正确的,除了我在函数结束时忘记了thread->start()调用on_request_thread()

崩溃是由于解析 ConfigObject 时出现问题而发生的,因此它与线程的创建无关。