diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-01 16:24:56 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-07-02 10:20:10 (GMT) |
commit | 200286b8e83918e785b61e4695443a3b77ebeaea (patch) | |
tree | adb10883bc34bc48f5c67da6eea892b6c8047257 /src/dbus | |
parent | 232f7af78d152518ccdcaaf1f42f89abb048ae5f (diff) | |
download | Qt-200286b8e83918e785b61e4695443a3b77ebeaea.zip Qt-200286b8e83918e785b61e4695443a3b77ebeaea.tar.gz Qt-200286b8e83918e785b61e4695443a3b77ebeaea.tar.bz2 |
Implement a support for getting return arguments out of invokeMethod
with QDBusInterface.
The problem was that I didn't know how to implement the operator= for
all types. But it turns out that this was possible all along: the only
types I have to implement the operator= for are the basic types, which
are already demarshalled.
The complex types are left in QDBusArgument semi-demarshalling, but we
have QDBusMetaType::demarshall, which takes a void* to an
already-constructed type and demarshalls into it. That's exactly what
the doctor ordered.
Task-number: 206765
Reviewed-By: Marius Bugge Monsen
Diffstat (limited to 'src/dbus')
-rw-r--r-- | src/dbus/qdbusinterface.cpp | 126 |
1 files changed, 118 insertions, 8 deletions
diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp index 6f61847..5f6df0a 100644 --- a/src/dbus/qdbusinterface.cpp +++ b/src/dbus/qdbusinterface.cpp @@ -51,6 +51,102 @@ QT_BEGIN_NAMESPACE +static void copyArgument(void *to, int id, const QVariant &arg) +{ + if (id == arg.userType()) { + switch (id) { + case QVariant::Bool: + *reinterpret_cast<bool *>(to) = arg.toBool(); + return; + + case QMetaType::UChar: + *reinterpret_cast<uchar *>(to) = arg.value<uchar>(); + return; + + case QMetaType::Short: + *reinterpret_cast<short *>(to) = arg.value<short>(); + return; + + case QMetaType::UShort: + *reinterpret_cast<ushort *>(to) = arg.value<ushort>(); + return; + + case QVariant::Int: + *reinterpret_cast<int *>(to) = arg.toInt(); + return; + + case QVariant::UInt: + *reinterpret_cast<uint *>(to) = arg.toUInt(); + return; + + case QVariant::LongLong: + *reinterpret_cast<qlonglong *>(to) = arg.toLongLong(); + return; + + case QVariant::ULongLong: + *reinterpret_cast<qulonglong *>(to) = arg.toULongLong(); + return; + + case QVariant::Double: + *reinterpret_cast<double *>(to) = arg.toDouble(); + return; + + case QVariant::String: + *reinterpret_cast<QString *>(to) = arg.toString(); + return; + + case QVariant::ByteArray: + *reinterpret_cast<QByteArray *>(to) = arg.toByteArray(); + return; + + case QVariant::StringList: + *reinterpret_cast<QStringList *>(to) = arg.toStringList(); + return; + } + + if (id == QDBusMetaTypeId::variant) { + *reinterpret_cast<QDBusVariant *>(to) = arg.value<QDBusVariant>(); + return; + } else if (id == QDBusMetaTypeId::objectpath) { + *reinterpret_cast<QDBusObjectPath *>(to) = arg.value<QDBusObjectPath>(); + return; + } else if (id == QDBusMetaTypeId::signature) { + *reinterpret_cast<QDBusSignature *>(to) = arg.value<QDBusSignature>(); + return; + } + + // those above are the only types possible + // the demarshaller code doesn't demarshall anything else + qFatal("Found a decoded basic type in a D-Bus reply that shouldn't be there"); + } + + // if we got here, it's either an un-dermarshalled type or a mismatch + if (arg.userType() != QDBusMetaTypeId::argument) { + // it's a mismatch + //qWarning? + return; + } + + // is this type registered? + const char *userSignature = QDBusMetaType::typeToSignature(id); + if (!userSignature || !*userSignature) { + // type not registered + //qWarning? + return; + } + + // is it the same signature? + QDBusArgument dbarg = arg.value<QDBusArgument>(); + if (dbarg.currentSignature() != QLatin1String(userSignature)) { + // not the same signature, another mismatch + //qWarning? + return; + } + + // we can demarshall + QDBusMetaType::demarshall(dbarg, id, to); +} + QDBusInterfacePrivate::QDBusInterfacePrivate(const QString &serv, const QString &p, const QString &iface, const QDBusConnection &con) : QDBusAbstractInterfacePrivate(serv, p, iface, con, true), metaObject(0) @@ -186,23 +282,37 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv) // we will assume that the input arguments were passed correctly QVariantList args; - for (int i = 1; i <= inputTypesCount; ++i) + int i = 1; + for ( ; i <= inputTypesCount; ++i) args << QVariant(inputTypes[i], argv[i]); // make the call - QPointer<QDBusInterface> qq = q; QDBusMessage reply = q->callWithArgumentList(QDBus::Block, methodName, args); - args.clear(); - // we ignore return values + if (reply.type() == QDBusMessage::ReplyMessage) { + // attempt to demarshall the return values + args = reply.arguments(); + QVariantList::ConstIterator it = args.constBegin(); + const int *outputTypes = metaObject->outputTypesForMethod(id); + int outputTypesCount = *outputTypes++; + + if (*mm.typeName()) { + // this method has a return type + if (argv[0] && it != args.constEnd()) + copyArgument(argv[0], *outputTypes++, *it); - // access to "this" or to "q" below this point must check for "qq" - // we may have been deleted! + // skip this argument even if we didn't copy it + --outputTypesCount; + ++it; + } - if (!qq.isNull()) - lastError = reply; + for (int j = 0; j < outputTypesCount && it != args.constEnd(); ++i, ++j, ++it) { + copyArgument(argv[i], outputTypes[j], *it); + } + } // done + lastError = reply; return -1; } } |