【问题标题】:Qt's signal / slot mechanism over the networkQt的网络信号/槽机制
【发布时间】:2016-07-22 15:59:45
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 你没有遗漏任何东西。
  • 呃....我不认为信号/槽机制设计用于在整个网络上工作。不过,我很高兴看到自己在这方面被证明是错误的。
  • 你是在重新发明 QtRemoteObjects 还是 QtDBus?
  • 您使用 QtRemoteObjects,它抽象了传输。
  • 这是旧的,但可能是相关的:bugreports.qt.io/browse/QTBUG-28833

标签: c++ qt


【解决方案1】:

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

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?

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

除非您想自己实现它,否则请使用现成的东西,例如 MIT 许可的 qt-remote-signals

【讨论】:

  • 到目前为止,它在没有任何进一步的库的情况下工作。我做的唯一不推荐的事情是直接使用 QGenericArgument ctor。
【解决方案2】:

你真的应该考虑使用 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 文件使用内置的 repc 编译器为服务器端(称为“源”)和客户端代码(称为“副本”)生成代码由 qmake 或 cmake 调用。 “源”调用的每个信号都会自动发送到每个连接的“副本”,并且“副本”调用的槽由“源”接收

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-09-11
    • 2021-02-12
    相关资源
    最近更新 更多