You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过qdbus向SetUnitProperties传递sba(sv)类型参数

QDBus调用systemd SetUnitProperties参数类型不匹配问题解决

问题背景

调用systemd的org.freedesktop.systemd1.Manager.SetUnitProperties方法时,出现参数类型不匹配错误:该方法要求参数类型为sba(sv),但当前代码传递的是sba{sv}(用QVariantMap实现),报错信息如下:

Invalid arguments 'sba{sv}' to call org.freedesktop.systemd1.Manager.SetUnitProperties(), expecting 'sba(sv)'

同时涉及StartTransientUnit方法的复杂参数ssa(sv)a(sa(sv)),同样存在数组类型参数构造的困惑。

错误原因

systemd的SetUnitProperties第三个参数是数组形式的键值对列表(DBus类型a(sv),每个元素是包含字符串键和变体值的结构体),而QVariantMap对应DBus的字典类型a{sv},两者类型不兼容,导致调用失败。

解决方案

1. 构造a(sv)类型参数

使用QList<QVariant>表示DBus的数组类型,每个数组元素用QVariantList封装(sv)结构体(第一个元素是字符串键,第二个是变体值),QDBus会自动将这种嵌套结构转换为DBus的a(sv)类型。

2. 构造StartTransientUnit的复杂参数

对于更复杂的a(sa(sv))类型,同样采用嵌套列表的方式:

  • 外层QList<QVariant>对应数组a(...)
  • 每个数组元素用QVariantList封装(sa(sv))结构体,包含一个字符串和一个a(sv)类型的数组(即上述的QList<QVariant>)

修改后的代码(针对SetUnitProperties)

int QUsbDeviceWrapper::swUpdate() {
    // Initialize the D-Bus connection
    QDBusConnection connection = QDBusConnection::systemBus();

    if (!connection.isConnected()) {
        qWarning("Cannot connect to the D-Bus system bus");
        return 1;
    }

    QDBusInterface managerInterface("org.freedesktop.systemd1",
                                    "/org/freedesktop/systemd1",
                                    "org.freedesktop.systemd1.Manager",
                                    connection);

    if (!managerInterface.isValid()) {
        qWarning("Failed to obtain interface to systemd1.Manager");
        return 1;
    }

    // Prepare arguments for the SetUnitProperties method
    QString serviceName = "swupdate-usb@sda1.service";
    bool runtime = true;

    // 构造a(sv)类型的属性数组:每个元素是(sv)结构体,用QVariantList表示
    QList<QVariant> properties;
    QVariantList stopProp;
    stopProp.append("StopWhenUnneeded");
    stopProp.append(QVariant(false));
    properties.append(stopProp);

    // Call the SetUnitProperties method
    QDBusMessage response = managerInterface.call("SetUnitProperties", serviceName, runtime, properties);

    if (response.type() == QDBusMessage::ErrorMessage) {
        qWarning() << "Error calling SetUnitProperties:" << response.errorMessage();
        return 1;
    }

    qDebug() << "SetUnitProperties call successful";

    return 0;
}

StartTransientUnit参数构造示例

// 构造单元属性数组a(sv)
QList<QVariant> unitProps;
QVariantList descProp;
descProp.append("Description");
descProp.append(QVariant("Transient Update Service"));
unitProps.append(descProp);

QVariantList execProp;
execProp.append("ExecStart");
execProp.append(QVariantList{"/usr/bin/swupdate", "-i", "/dev/sda1"}); // 传递命令行参数数组
unitProps.append(execProp);

// 构造a(sa(sv))类型的单元条目数组
QList<QVariant> transientEntries;
QVariantList serviceEntry;
serviceEntry.append("swupdate-usb@sda1.service");
serviceEntry.append(unitProps);
transientEntries.append(serviceEntry);

// 调用StartTransientUnit
QDBusMessage response = managerInterface.call("StartTransientUnit",
                                              "swupdate-usb@sda1.service",
                                              "replace",
                                              unitProps,
                                              transientEntries);

验证

修改后调用SetUnitProperties将不再出现类型不匹配错误,可成功修改systemd单元属性。

内容的提问来源于stack exchange,提问作者gomme600

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:52:02