Qt在网络上的信号/时隙机制

Qt's signal / slot mechanism over the network

本文关键字:时隙 机制 信号 网络 Qt      更新时间:2023-10-16

我希望能够通过网络发送Qt信号。使用Qt的元类型系统,序列化信号调用是非常直接的

  • 使用静态方法::fromSignal创建qMetaMethod
  • 使用创建的元方法获取方法名称、参数名称、它们的typeId [1]和值
  • 将所有内容打包成您喜欢的格式(JSON、XML)并发送

但到目前为止,我还不知道如何使用序列化数据调用信号:QMetaObject::invokeMethod(..)将信号/方法名称作为字符串。问题是参数:它们必须以QGenericArgument的形式提供,并且只能通过使用Q_ARG宏来创建,该宏需要实际类型(而不是名称或typeId的字符串)和相关值。此外,必须在编译时定义参数的数量,没有采用参数列表的invokeMethod(..)

我是不是错过了什么?或者有更好/替代的方法吗?

[1]进一步的问题:当使用Q_DECLARE_METATYPE(..)注册类型时,我如何确保它们总是获得相同的typeId?

不能自己创建QGenericArgument是错误的。建议您不要这样做,但无论如何,您尝试做的事情都非常依赖于实现。它没有太多内容:您提供了一个类型名称和一个指向给定类型的数据的指针。例如:

QGenericArgument one() {
  static const char type[] = "int";
  static const int data = "1";
  return QGenericArgument{type, (void*)&data);
}

有关更多示例代码,请参阅此答案的Introspectable Visitor部分。

如何确保类型在使用Q_DECLARE_METATYPE(..)注册时始终获得相同的typeId?

你没有。您应该使用类型名称,并且每个进程都应该在本地将这些名称解析为typeid。

除非你想自己实现它,否则使用现成的东西,比如麻省理工学院许可的qt远程信号。

你真的应该考虑使用Qt远程对象,因为它们可以完成你需要的一切,甚至更多(心跳、断开连接后自动重新连接、在引擎盖下使用QLocalSocket或QTcpSocket等)据我所知,它是最容易通过网络获取信号的方法。

https://doc.qt.io/qt-5/qtremoteobjects-index.html

您只需要定义.rep文本文件,它就像IDL定义文件

class MyRemoteObject {
{
    SIGNAL(foo(int value));
    SIGNAL(bar(float value));
    SLOT(somethingChanged(int newValue));
};

然后.rep文件使用qmake或cmake调用的内置repc编译器生成服务器端的代码(称为"源")和客户端的代码(也称为"副本")。"源"调用的每个信号都会自动发送到每个连接的"副本","副本"调用的插槽由"源"接收