366void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
371 QString className = interface;
372 className.replace(u'.',
"::"_L1);
373 if (className.isEmpty())
374 className =
"QDBusInterface"_L1;
376 QVarLengthArray<uint> idata;
377 idata.resize(
sizeof(QDBusMetaObjectPrivate) /
sizeof(uint));
379 qsizetype methodParametersDataSize =
380 ((aggregateParameterCount(signals_)
381 + aggregateParameterCount(methods)) * 2)
385 QDBusMetaObjectPrivate *header =
reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
386 static_assert(QMetaObjectPrivate::OutputRevision == 14,
"QtDBus meta-object generator should generate the same version as moc");
387 header->revision = QMetaObjectPrivate::OutputRevision;
388 header->className = 0;
389 header->metaObjectHashIndex = -1;
390 header->classInfoCount = 0;
391 header->classInfoData = 0;
392 header->methodCount =
int(signals_.size() + methods.size());
393 header->methodData =
int(idata.size());
394 header->propertyCount =
int(properties.size());
395 header->propertyData =
int(header->methodData + header->methodCount *
396 QMetaObjectPrivate::IntsPerMethod + methodParametersDataSize);
397 header->enumeratorCount = 0;
398 header->enumeratorData = 0;
399 header->constructorCount = 0;
400 header->constructorData = 0;
401 header->flags = RequiresVariantMetaObject | AllocatedMetaObject;
402 header->signalCount = signals_.size();
404 header->propertyDBusData =
int(header->propertyData + header->propertyCount
405 * QMetaObjectPrivate::IntsPerProperty);
406 header->methodDBusData =
int(header->propertyDBusData + header->propertyCount * intsPerProperty);
408 qsizetype data_size = idata.size() +
409 (header->methodCount * (QMetaObjectPrivate::IntsPerMethod+intsPerMethod)) + methodParametersDataSize +
410 (header->propertyCount * (QMetaObjectPrivate::IntsPerProperty+intsPerProperty));
413 std::array<std::reference_wrapper<
const MethodMap>, 2> methodMaps = { signals_, methods };
415 for (
const auto &methodMap : methodMaps) {
416 for (
const Method &mm : methodMap.get())
417 data_size += 2 + mm.inputTypes.size() + mm.outputTypes.size();
419 idata.resize(data_size + 1);
421 QMetaStringTable strings(className.toLatin1());
423 qsizetype offset = header->methodData;
424 qsizetype parametersOffset = offset + header->methodCount * QMetaObjectPrivate::IntsPerMethod;
425 qsizetype signatureOffset = header->methodDBusData;
426 qsizetype typeidOffset = header->methodDBusData + header->methodCount * intsPerMethod;
427 idata[typeidOffset++] = 0;
429 qsizetype totalMetaTypeCount = properties.size();
430 ++totalMetaTypeCount;
431 for (
const auto &methodMap : methodMaps) {
432 for (
const Method &mm : methodMap.get()) {
433 qsizetype argc = mm.inputTypes.size() + qMax(qsizetype(0), mm.outputTypes.size() - 1);
434 totalMetaTypeCount += argc + 1;
437 QMetaType *metaTypes =
new QMetaType[totalMetaTypeCount];
441 qsizetype currentMethodMetaTypeOffset = properties.size() + 1;
443 for (
const auto &methodMap : methodMaps) {
444 for (
const Method &mm : methodMap.get()) {
445 qsizetype argc = mm.inputTypes.size() + qMax(qsizetype(0), mm.outputTypes.size() - 1);
447 idata[offset++] = strings.enter(mm.name);
448 idata[offset++] = argc;
449 idata[offset++] = parametersOffset;
450 idata[offset++] = strings.enter(mm.tag);
451 idata[offset++] = mm.flags;
452 idata[offset++] = currentMethodMetaTypeOffset;
455 for (qsizetype i = -1; i < argc; ++i) {
459 if (!mm.outputTypes.isEmpty()) {
460 type = mm.outputTypes.first();
462 type = IsUnresolvedType | strings.enter(mm.rawReturnType);
465 type = QMetaType::Void;
467 }
else if (i < mm.inputTypes.size()) {
468 type = mm.inputTypes.at(i);
470 Q_ASSERT(mm.outputTypes.size() > 1);
471 type = mm.outputTypes.at(i - mm.inputTypes.size() + 1);
473 typeName = QMetaType(type).name();
474 typeName.append(
'&');
475 type = QMetaType::UnknownType;
478 if (!typeName.isEmpty())
479 typeInfo = IsUnresolvedType | strings.enter(typeName);
482 metaTypes[currentMethodMetaTypeOffset++] = QMetaType(type);
483 idata[parametersOffset++] = typeInfo;
486 for (qsizetype i = 0; i < argc; ++i)
487 idata[parametersOffset++] = strings.enter(mm.parameterNames.at(i));
489 idata[signatureOffset++] = typeidOffset;
490 idata[typeidOffset++] = mm.inputTypes.size();
491 memcpy(idata.data() + typeidOffset, mm.inputTypes.data(), mm.inputTypes.size() *
sizeof(uint));
492 typeidOffset += mm.inputTypes.size();
494 idata[signatureOffset++] = typeidOffset;
495 idata[typeidOffset++] = mm.outputTypes.size();
496 memcpy(idata.data() + typeidOffset, mm.outputTypes.data(), mm.outputTypes.size() *
sizeof(uint));
497 typeidOffset += mm.outputTypes.size();
501 Q_ASSERT(offset == header->methodData + header->methodCount * QMetaObjectPrivate::IntsPerMethod);
502 Q_ASSERT(parametersOffset == header->propertyData);
503 Q_ASSERT(signatureOffset == header->methodDBusData + header->methodCount * intsPerMethod);
504 Q_ASSERT(typeidOffset == idata.size());
505 offset += methodParametersDataSize;
506 Q_ASSERT(offset == header->propertyData);
509 signatureOffset = header->propertyDBusData;
510 for (
const auto &[name, mp] : std::as_const(properties).asKeyValueRange()) {
512 idata[offset++] = strings.enter(name);
513 Q_ASSERT(mp.type != QMetaType::UnknownType);
514 idata[offset++] = mp.type;
515 idata[offset++] = mp.flags;
516 idata[offset++] = -1;
519 idata[signatureOffset++] = strings.enter(mp.signature);
520 idata[signatureOffset++] = mp.type;
522 metaTypes[propertyId++] = QMetaType(mp.type);
524 metaTypes[propertyId] = QMetaType();
526 Q_ASSERT(offset == header->propertyDBusData);
527 Q_ASSERT(signatureOffset == header->methodDBusData);
529 char *string_data =
new char[strings.blobSize()];
530 strings.writeBlob(string_data);
532 uint *uint_data =
new uint[idata.size()];
533 memcpy(uint_data, idata.data(), idata.size() *
sizeof(uint));
536 obj->d.data = uint_data;
537 obj->d.relatedMetaObjects =
nullptr;
538 obj->d.static_metacall =
nullptr;
539 obj->d.extradata =
nullptr;
540 obj->d.stringdata =
reinterpret_cast<
const uint *>(string_data);
541 obj->d.superdata = &QDBusAbstractInterface::staticMetaObject;
542 obj->d.metaTypes =
reinterpret_cast<QtPrivate::QMetaTypeInterface *
const *>(metaTypes);
574QDBusMetaObject *QDBusMetaObject::createMetaObject(
const QString &interface,
const QString &xml,
575 QHash<QString, QDBusMetaObject *> &cache,
578 error = QDBusError();
579 QDBusIntrospection::Interfaces parsed = QDBusIntrospection::parseInterfaces(xml);
581 QDBusMetaObject *we =
nullptr;
582 QDBusIntrospection::Interfaces::ConstIterator it = parsed.constBegin();
583 QDBusIntrospection::Interfaces::ConstIterator end = parsed.constEnd();
584 for ( ; it != end; ++it) {
586 bool us = it.key() == interface;
588 QDBusMetaObject *obj = cache.value(it.key(), 0);
589 if (!obj && (us || !interface.startsWith(
"local."_L1 ))) {
591 obj =
new QDBusMetaObject;
592 QDBusMetaObjectGenerator generator(it.key(), it.value().constData());
593 generator.write(obj);
595 if ((obj->cached = !it.key().startsWith(
"local."_L1)))
597 cache.insert(it.key(), obj);
612 if (parsed.isEmpty()) {
614 we =
new QDBusMetaObject;
615 QDBusMetaObjectGenerator generator(interface,
nullptr);
619 }
else if (interface.isEmpty()) {
621 it = parsed.constBegin();
622 QDBusIntrospection::Interface merged = *it.value().constData();
624 for (++it; it != end; ++it) {
625 merged.annotations.insert(it.value()->annotations);
626 merged.methods.unite(it.value()->methods);
627 merged.signals_.unite(it.value()->signals_);
628 merged.properties.insert(it.value()->properties);
631 merged.name =
"local.Merged"_L1;
632 merged.introspection.clear();
634 we =
new QDBusMetaObject;
635 QDBusMetaObjectGenerator generator(merged.name, &merged);
642 error = QDBusError(QDBusError::UnknownInterface,
643 "Interface '%1' was not found"_L1.arg(interface));