gpt4 book ai didi

emacs - 如何使用 Emacs 的 DBUS 接口(interface)?

转载 作者:行者123 更新时间:2023-12-02 13:08:22 25 4
gpt4 key购买 nike

我查看了 dbus 包,似乎所有函数都内置在 C 源代码中,并且没有它们的文档。

如何使用 dbus-call-method功能?

最佳答案

我刚刚遇到了同样的问题,发现在谷歌搜索时出现的 emacs-fu 文章对我的需求来说有点太基本了。

特别是我想通过 dbus 导出我自己的 elisp 方法,但在理解 dbus 术语以及它如何应用于 emacs dbus 接口(interface)时遇到了问题。

首先要检查,emacs 文档,C-h f dbus-register-method

dbus-register-method is a built-in function in `C source code'.

(dbus-register-method BUS SERVICE PATH INTERFACE METHOD HANDLER)

Register for method METHOD on the D-Bus BUS.

BUS is either the symbol `:system' or the symbol `:session'.

SERVICE is the D-Bus service name of the D-Bus object METHOD is
registered for. It must be a known name.

PATH is the D-Bus object path SERVICE is registered. INTERFACE is the
interface offered by SERVICE. It must provide METHOD. HANDLER is a
Lisp function to be called when a method call is received. It must
accept the input arguments of METHOD. The return value of HANDLER is
used for composing the returning D-Bus message.

BUS 只是 :session 或 :system (我想你可能几乎总是想像桌面应用程序一样使用 :session )。

SERVICE 是总线上应用程序的唯一名称,如地址或域名。 Dbus.el 定义 dbus-service-emacs作为“org.gnu.Emacs”。

PATH 适用于不同类型的应用程序功能,就像 SERVICE 适用于不同的应用程序本身。例如,某个 emacs 模块可能会在 org.gnu.Emacs SERVICE 下的/ModuleName PATH 中公开功能。

INTERFACE 就像编程中的接口(interface)一样。它是一种规范,告诉其他 dbus 客户端如何与您的应用程序公开的对象进行通信。例如,它包含您的方法的类型签名。
因此,您可能有一个类似这样的接口(interface):在服务 org.gnu.Emacs 下,在路径/ModuleName 中,您将找到一个名为 helloworld 的方法,该方法将接受零参数并返回一个字符串。

对我来说很难弄清楚的是:如何为我的方法定义接口(interface)?

查看 dbus.el 你会发现有 dbus-interface-introspectable (除其他外)定义,它只包含一个字符串“org.freedesktop.DBus.Introspectable”,它命名一个标准接口(interface),只公开一个方法:
org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)

(链接到规范 http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable )

这就是客户端调用的方法,以了解哪些应用程序在 dbus 上公开。所以我们可以使用该方法来查看其他应用程序如何在 dbus 上宣传他们的东西,然后我们可以实现我们自己的 Introspect 方法,只是模仿其他人正在做的事情,一切都会好起来的。

但是请注意,规范说应用程序可以实现 Introspectable 接口(interface),它们不必这样做。其实你可以调用 dbus-register-method用一个空字符串作为接口(interface)就好了(看起来什么都可以)。您将能够调用您的方法。但是,我总是遇到 NoReply 错误和应用程序挂起等待 dbus 响应的问题,当我弄清楚如何使我的东西可自省(introspection)时,这些问题就消失了。所以我假设 Introspect() 经常被期望。

所以让我们这样做:
(defun say-world ()
;; you need to map between dbus and emacs datatypes, that's what :string is for
;; if you're returning just one value that should work automatically, otherwise
;; you're expected to put your return values in a list like I am doing here
(list :string "world"))

(dbus-register-method
:session
"org.test.emacs"
"/helloworld"
"org.test.emacs"
"hello"
'say-world)

这就是我们想要实现的,因此想要为(命名为“org.test.emacs”)定义一个接口(interface)。您可以像这样使用它并尝试使用 qdbus org.test.emacs /helloworld org.test.emacs.hello 调用 hello 方法。 .它应该可以工作,对我来说,它仅在等待 20 秒后才有效(使应用程序挂起),但它可以工作。

现在让它自省(introspection):
(defun dbus-test-slash-introspect ()
"<node name='/'>
<interface name='org.freedesktop.DBus.Introspectable'>
<method name='Introspect'>
<arg name='xml_data' type='s' direction='out'/>
</method>
</interface>
<node name='helloworld'>
</node>
</node>")

(dbus-register-method
:session
"org.test.emacs"
"/"
dbus-interface-introspectable
"Introspect"
'dbus-test-slash-introspect)

(defun dbus-test-slash-helloworld-introspect ()
"<node name='/helloworld'>
<interface name='org.freedesktop.DBus.Introspectable'>
<method name='Introspect'>
<arg name='xml_data' type='s' direction='out'/>
</method>
</interface>
<interface name='org.test.emacs'>
<method name='hello'>
<arg name='' direction='out' type='s' />
</method>
</interface>
</node>")

(dbus-register-method
:session
"org.test.emacs"
"/helloworld"
dbus-interface-introspectable
"Introspect"
'dbus-test-slash-helloworld-introspect)

我们去吧。我们只定义了两个 Introspect 方法(一个用于路径层次结构的每一层)并返回一些手写的 xml,告诉其他应用程序/helloworld 路径和其中的 hello 方法。请注意 dbus-test-slash-helloworld-introspect包含 <interface name="org.test.emacs">...</interface>它对我们的方法有一个类型签名,也就是说,就我而言,当我们向 dbus 注册我们的方法时使用的接口(interface)的定义。

评估所有这些并使用 qdbus:
~> qdbus org.test.emacs
/
/helloworld

~> qdbus org.test.emacs /
method QString org.freedesktop.DBus.Introspectable.Introspect()

~> qdbus org.test.emacs /helloworld
method QString org.freedesktop.DBus.Introspectable.Introspect()
method QString org.test.emacs.helloworld()

~> qdbus org.test.emacs /helloworld org.test.emacs.hello
world

万岁,按预期工作,没有挂起或 NoReply 错误。

最后一件事,您可能会尝试像这样测试您的方法:
(dbus-call-method :session "org.test.emacs" "/helloworld" "org.test.emacs" "hello" :timeout 1000)

并发现它只是超时并想知道为什么。那是因为如果您在同一个 emacs 实例中注册并调用一个方法,那么 emacs 将等待自己回答。没有花哨的线程,在那种情况下你总是会得到一个 NoReply 答案。

如果你必须在同一个 emacs 实例中调用和注册一个方法,你可以使用 dbus-call-method-asynchronously像这样:
(defun handle-hello (hello)
(print hello))

(dbus-call-method-asynchronously :session "org.test.emacs" "/helloworld" "org.test.emacs" "hello" 'handle-hello)

关于emacs - 如何使用 Emacs 的 DBUS 接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4474290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com