我查看了dbus包,似乎所有的功能都内置在C源代码中,并且没有相关的文档。
如何使用dbus-call-method
功能?
答案 0 :(得分:23)
我遇到了同样的问题,发现当google搜索有点过于基本以满足我的需求时出现的emacs-fu文章。
特别是我想通过dbus导出我自己的elisp方法,并且难以理解dbus术语以及它如何应用于emacs dbus接口。
首先要查看,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(您可能几乎总是想要使用:我认为会话就像桌面应用程序一样)。
SERVICE是总线上应用程序的唯一名称,如地址或域名。 Dbus.el将dbus-service-emacs
定义为“org.gnu.Emacs”。
PATH是针对不同类型的应用程序功能,不同的应用程序本身是什么。例如,某个emacs模块可能会在org.gnu.Emacs SERVICE下的/ ModuleName PATH中公开功能。
INTERFACE就像编程中的界面。它是一个规范,告诉其他dbus客户端如何与您的应用程序公开的对象进行通信。它包含例如方法的类型签名。 所以你可能有一个类似的界面:在服务org.gnu.Emacs下,在路径/ ModuleName中,你会找到一个名为helloworld的方法,它将采用零参数并返回一个字符串。
难以理解的是:我如何为我的方法定义界面?
在dbus.el周围你会发现定义了dbus-interface-introspectable
(等等),只包含一个字符串“org.freedesktop.DBus.Introspectable”,它命名一个标准接口,只暴露一个方法:
org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
(链接到规范http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable)
这是客户调用以了解dbus上暴露的应用程序的方法。因此,我们可以使用该方法来查看其他应用程序如何在dbus上宣传他们的东西,然后我们可以实现我们自己的Introspect方法,只是模仿其他人正在做的事情,一切都会好的。
但请注意,规范说应用程序可能实现Introspectable接口,但他们不必这样做。实际上你可以用一个空字符串作为接口来调用dbus-register-method
就好了(似乎任何东西都可以)。你可以打电话给你的方法。然而,当我想出如何使我的东西内省时,我总是遇到NoReply错误和应用程序悬挂等待dbus响应的问题。所以我认为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”)定义接口。您可以像这样使用它并尝试使用qdbus org.test.emacs /helloworld org.test.emacs.hello
调用hello方法。它应该可以工作,对我而言,只有在等待20秒后才能工作(使应用程序挂起),但它可以工作。
现在让它让人反省:
(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注册方法时使用的接口定义。
评估所有这些并使用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
Hooray,按预期工作,没有挂起或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)
答案 1 :(得分:8)
谷歌救援......按照示例的链接,这不是我的代码所以我不会把它放在这里。
http://emacs-fu.blogspot.com/2009/01/using-d-bus-example.html
答案 2 :(得分:5)
这是测试dbus功能的安全方法:
(defun dbus-capable ()
"Check if dbus is available"
(unwind-protect
(let (retval)
(condition-case ex
(setq retval (dbus-ping :session "org.freedesktop.Notifications"))
('error
(message (format "Error: %s - No dbus" ex))))
retval)))
这是一种发送dbus通知的方法:
(defun mbug-desktop-notification (summary body timeout icon)
"call notification-daemon method METHOD with ARGS over dbus"
(if (dbus-capable)
(dbus-call-method
:session ; Session (not system) bus
"org.freedesktop.Notifications" ; Service name
"/org/freedesktop/Notifications" ; Service path
"org.freedesktop.Notifications" "Notify" ; Method
"emacs"
0
icon
summary
body
'(:array)
'(:array :signature "{sv}")
':int32 timeout)
(message "Oh well, you're still notified")))
答案 3 :(得分:4)
或者,只需在Emacs中评估以下内容:
(info "(dbus)")