簡體   English   中英

我如何使用Emacs的DBUS界面?

[英]How do I use Emacs's DBUS interface?

我查了一下dbus包,似乎所有的函數都內置在C源代碼中,並且沒有相關的文檔。

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

我剛遇到同樣的問題,發現當google搜索有點過於基本以滿足我的需求時出現的emacs-fu文章。

特別是我想通過dbus導出我自己的elisp方法,並且難以理解dbus術語以及它如何應用於emacs dbus接口。

首先要看看,emacs文檔,Ch 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

萬歲,按預期工作,沒有掛起或NoReply錯誤。

最后一件事,您可能會嘗試像這樣測試您的方法:

(dbus-call-method :session "org.test.emacs" "/helloworld" "org.test.emacs" "hello" :timeout 1000)

並發現它只是超時並想知道為什么。 那是因為如果您在同一個emacs實例中注冊並調用方法,那么emacs將等待自己回答。 沒有花哨的線程,在那種情況下你總能獲得NoReply答案。

如果你必須在同一個emacs實例中調用和注冊方法,你可以像這樣dbus-call-method-asynchronously使用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)

谷歌救援......按照示例的鏈接,這不是我的代碼,所以我不會把它放在這里。

http://emacs-fu.blogspot.com/2009/01/using-d-bus-example.html

這是測試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")))

或者,只需在Emacs中評估以下內容:

(info "(dbus)")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM