我正在阅读D-Bus API 设计指南:
公共API的接口文件应安装到$(datadir)/dbus-1/interfaces,以便其他服务可以加载它们。
好的...为了了解这些接口文件是如何工作的,我打开该文件
/usr/share/dbus-1/interfaces/org.gnome.Shell.Screenshot.xml
(我使用的是Ubuntu 20.04)
<node>
<interface name="org.gnome.Shell.Screenshot">
...
<method name="PickColor">
<arg type="a{sv}" direction="out" name="result"/>
</method>
嗯,我看到了接口名称,我看到了方法名称,但这还不够。如果我想使用
dbus-send
来调用这个方法
$ dbus-send --print-reply --dest=<service.name> </path/to/object> org.gnome.Shell.Screenshot.PickColor
我需要
<service.name>
和 <path/to/object>
,这个 xml
文件不提供。
问题是:如果这个文件没有提供有关服务接口的完整信息,它的用途是什么?它被
dbus-daemon
或任何其他程序使用吗?某些东西真的需要这样的文件吗?我是否应该得出这样的结论:未提供 中对象路径的 xml 文件是不完整的?此类文件是否还应该提及服务已知名称(在本例中为org.gnome.Shell.Screenshot
)?
org.freedesktop.DBus.Introspectable
接口有一种方法:
org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
对象实例可以实现
Introspect
,它返回对象的 XML 描述。内省格式记录在:
https://dbus.freedesktop.org/doc/dbus-specation.html#introspection-format
在命令行上使用
busctl
,我可以使用 list
获取所有服务,tree
获取所有对象,然后使用 intropspect
查找 API。使用这三个命令我可以发现系统上的 D-Bus 服务
$ busctl list
$ busctl tree <service>
$ busctl introspect <service> <object>
您在问题中提到的服务位于会话/用户总线上,因此它是:
$ busctl --user list | grep Screenshot
NAME PID PROCESS USER CONNECTION UNIT SESSION DESCRIPTION
---------------------------------------------------------------------------------------------------------------------------------
org.gnome.Screenshot - - - (activatable) - - -
org.gnome.Shell.Screenshot 1259 gnome-shell LinuxMachine1 :1.37 [email protected] - -
$ busctl --user tree org.gnome.Shell.Screenshot
├─/StatusNotifierWatcher
└─/org
├─/org/freedesktop
│ ├─/org/freedesktop/Notifications
│ └─/org/freedesktop/portal
│ └─/org/freedesktop/portal/desktop
├─/org/gnome
│ ├─/org/gnome/Mutter
│ │ ├─/org/gnome/Mutter/DisplayConfig
│ │ └─/org/gnome/Mutter/IdleMonitor
│ │ └─/org/gnome/Mutter/IdleMonitor/Core
│ ├─/org/gnome/ScreenSaver
│ ├─/org/gnome/SessionManager
│ │ └─/org/gnome/SessionManager/EndSessionDialog
│ ├─/org/gnome/Shell
│ │ ├─/org/gnome/Shell/AudioDeviceSelection
│ │ ├─/org/gnome/Shell/Introspect
│ │ ├─/org/gnome/Shell/Screencast
│ │ ├─/org/gnome/Shell/Screenshot
│ │ └─/org/gnome/Shell/Wacom
│ └─/org/gnome/keyring
│ └─/org/gnome/keyring/Prompter
└─/org/gtk
├─/org/gtk/MountOperationHandler
└─/org/gtk/Notifications
$ busctl --user introspect org.gnome.Shell.Screenshot /org/gnome/Shell/Screenshot
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
org.gnome.Shell.Screenshot interface - - -
.FlashArea method iiii - -
.PickColor method - a{sv} -
.Screenshot method bbs bs -
.ScreenshotArea method iiiibs bs -
.ScreenshotWindow method bbbs bs -
.SelectArea method - iiii -
为了完整起见,运行与您相同的命令:
$ busctl --user call org.gnome.Shell.Screenshot /org/gnome/Shell/Screenshot org.gnome.Shell.Screenshot PickColor
a{sv} 1 "color" (ddd) 1 1 1
答案就在名称中:它是一个 D-Bus interface 文件。它定义了一个“接口”,而不是该接口的实例。 D-Bus 中的接口可能有零个或多个实例,并且它们可能是动态的。所以它们的路径不能在 XML 文件中指定。 如果现在设计 D-Bus,也许这个 XML 文件的结构或实现方式会有所不同。但这就是这样的。