I want to be able to send Qt signals over the network. Serializing a signal call is quite straight forward using Qt's meta type system:
qMetaMethod
using the static method ::fromSignal
[1]
and values using the created meta method.But so far I could not figure out how to invoke a signal using serialized data: QMetaObject::invokeMethod(..)
takes the signal / method name as string. The problem are the arguments: They must be provided as QGenericArgument
and those can only be created by using the Q_ARG
macro which requires the actual type (not a string of it's name or the typeId
) and the concerning value. Also the number of arguments must be defined at compile time, there is is no invokeMethod(..)
which takes a list of arguments.
Am I missing something? Or is there a better / alternative way to do this?
[1]
Further question: How do I ensure that types always get the same typeId when they are registered using Q_DECLARE_METATYPE(..)
?
It is false that you can't create a QGenericArgument
yourself. You're advised not to, but what you're trying to do is very implementation-dependent anyway. There isn't much to it: you provide a type name, and a pointer to the data of a given type. E.g.:
QGenericArgument one() {
static const char type[] = "int";
static const int data = "1";
return QGenericArgument{type, (void*)&data);
}
See the Introspectable Visitor section of this answer for more example code.
How do I ensure that types always get the same typeId when they are registered using
Q_DECLARE_METATYPE(..)
?
You don't. You should be using type names, and each process should resolve these to typeids locally.
Unless you want to implement it yourself, use something ready made, like the MIT-licensed qt-remote-signals.
You really should consider using Qt Remote Object since they accomplish everything that you need and more (heartbeat, automatic re-connection upon disconnect, works with either QLocalSocket or QTcpSocket under the hood, etc) It the easiest to get signals across the network with minimal effort that I know of.
https://doc.qt.io/qt-5/qtremoteobjects-index.html
You just need to define .rep
text file, which is like an IDL definition file
class MyRemoteObject {
{
SIGNAL(foo(int value));
SIGNAL(bar(float value));
SLOT(somethingChanged(int newValue));
};
and then it takes that .rep
file to generate code for the server side (known as 'source') and code for the client side (known as 'replica') using a built-in repc
compiler that is called by qmake or cmake. Every signals called by the 'source' is automatically sent across every connected 'replicas', and slots called by 'replicas' are received by the 'source'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With