Qt通过网络的信号/插槽机制

时间:2016-07-22 15:59:46

标签: c++ qt

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

  • 使用静态方法qMetaMethod
  • 创建::fromSignal
  • 使用创建的元方法获取方法名称,参数名称,其typeIds [1]和值。
  • 将所有内容打包为您的首选格式(JSON,XML)并发送。

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

我错过了什么吗?或者有更好/替代方法来做到这一点?

[1]进一步的问题:如何确保类型在使用Q_DECLARE_METATYPE(..)注册时始终获得相同的typeId?

2 个答案:

答案 0 :(得分:3)

您无法自己创建QGenericArgument,这是错误的。你被告知不要这样做,但你要做的事情仍然是依赖于实现的。没有太多内容:您提供类型名称和指向给定类型数据的指针。 E.g:

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

有关更多示例代码,请参阅this answer的Introspectable Visitor部分。

  

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

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

除非您想自己实施,否则请使用现成的东西,例如获得麻省理工学院许可的qt-remote-signals

答案 1 :(得分:1)

您真的应该考虑使用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));
};

,然后使用内置的{{1},使用一个.rep文件为服务器端生成代码(称为“源”),为客户端生成代码(称为“副本”)。 }由qmake或cmake调用的编译器。由“源”调用的每个信号都会在每个连接的“副本”之间自动发送,由“副本”调用的插槽将由“源”接收