2010-12-17 17 views

Trả lời

23

Tôi chỉ có cùng một vấn đề và tìm thấy bài viết emacs-fu mà đi lên khi googling một chút quá cơ bản cho nhu cầu của tôi.

Cụ thể là tôi muốn xuất các phương thức elisp của riêng mình qua dbus, và có vấn đề về ý nghĩa của thuật ngữ dbus và cách nó áp dụng cho giao diện dbus emacs.

Điều đầu tiên để kiểm tra, tài liệu emacs, Ch f dbus đăng ký-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 chỉ sẽ là: phiên hoặc: Hệ thống (nơi bạn có thể hầu như luôn luôn muốn sử dụng: phiên giống như ứng dụng trên máy tính để bàn mà tôi cho là).

SERVICE là tên duy nhất cho ứng dụng trên xe buýt, như địa chỉ hoặc tên miền. Dbus.el định nghĩa dbus-service-emacs là "org.gnu.Emacs".

PATH là các loại chức năng ứng dụng khác nhau mà SERVICE cung cấp cho các ứng dụng khác nhau. Ví dụ: một mô-đun emacs nhất định có thể hiển thị chức năng trong PATH/ModuleName dưới dịch vụ org.gnu.Emacs.

INTERFACE giống như một giao diện trong lập trình. Nó là một đặc tả cho các máy khách dbus biết cách giao tiếp với (các) đối tượng mà ứng dụng của bạn trưng ra. Nó chứa các chữ ký kiểu mẫu cho các phương thức của bạn. Vì vậy, bạn có thể có một giao diện cho biết một cái gì đó như: dưới dịch vụ org.gnu.Emacs, trong đường dẫn/ModuleName, bạn sẽ tìm thấy một phương thức có tên helloworld sẽ lấy 0 đối số và trả về một chuỗi.

Điều khó khăn để tìm ra cho tôi là: làm cách nào để xác định giao diện cho phương pháp của tôi?

Poking xung quanh dbus.el bạn sẽ thấy rằng có dbus-interface-introspectable (trong số những người khác) được xác định, đó chỉ chứa một chuỗi "org.freedesktop.DBus.Introspectable", mà tên một giao diện tiêu chuẩn mà chỉ cho thấy một phương pháp:

org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data) 

(liên kết đến spec http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable)

Và đó là phương pháp được gọi là bởi khách hàng để tìm hiểu về những ứng dụng nào phơi bày trên dbus. Vì vậy, chúng tôi có thể sử dụng phương pháp đó để xem các ứng dụng khác quảng cáo nội dung của họ trên dbus như thế nào, và sau đó chúng tôi có thể thực hiện phương pháp Introspect của chính mình.

Lưu ý rằng thông số nói rằng các ứng dụng có thể triển khai giao diện Introspectable, chúng không phải. Trong thực tế, bạn có thể gọi dbus-register-method tốt với một chuỗi rỗng như giao diện (bất cứ điều gì sẽ làm điều đó có vẻ). Bạn sẽ có thể gọi phương thức của bạn.Tuy nhiên tôi đã luôn luôn lỗi NoReply và các vấn đề với các ứng dụng treo chờ đợi một phản ứng từ dbus mà đi xa khi tôi tìm ra cách làm cho nội dung của tôi introspectable. Vì vậy, tôi cho rằng Introspect() được mong đợi khá thường xuyên.

Vì vậy, cho phép thực hiện điều này:

(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) 

Đó là những gì chúng tôi muốn thực hiện và do đó muốn xác định một giao diện cho (có tên là "org.test.emacs"). Bạn có thể sử dụng nó giống như vậy và cố gắng gọi phương thức hello với qdbus org.test.emacs /helloworld org.test.emacs.hello. Nó sẽ làm việc, đối với tôi nó chỉ hoạt động sau 20 giây chờ đợi (làm cho ứng dụng treo), nhưng nó hoạt động.

Bây giờ cho phép làm cho nó introspectable:

(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) 

Có chúng tôi đi. Chúng ta chỉ định nghĩa hai phương thức Introspect (một cho mỗi mức của hierachy path) và trả về một số xml viết tay cho các ứng dụng khác biết về đường dẫn/helloworld và phương thức hello bên trong nó. Lưu ý rằng dbus-test-slash-helloworld-introspect chứa <interface name="org.test.emacs">...</interface> có chữ ký kiểu cho phương pháp của chúng tôi, đó là, theo như tôi quan tâm, định nghĩa của giao diện chúng tôi sử dụng khi đăng ký phương thức của chúng tôi với dbus.

Đánh giá tất cả những gì và poke xung quanh với 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 

Hoan hô, làm việc như mong đợi, không treo hoặc lỗi NoReply.

Một điều cuối cùng, bạn có thể thử để kiểm tra phương pháp của bạn như vậy:

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

và thấy rằng nó chỉ thờ gian tạm ngưng và tự hỏi tại sao. Đó là bởi vì nếu bạn đăng ký và gọi một phương thức từ bên trong cùng một thể hiện emacs thì các emacs sẽ đợi chính nó để trả lời. Không có luồng ưa thích nào đang diễn ra, bạn sẽ luôn nhận được câu trả lời NoReply trong tình huống đó.

Nếu bạn phải gọi và đăng ký một phương thức trong cùng một ví dụ emacs bạn có thể sử dụng dbus-call-method-asynchronously như vậy:

(defun handle-hello (hello) 
    (print hello)) 

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

Đây phải là câu trả lời hàng đầu. –

+0

Điều này thật tuyệt. Bạn có cân nhắc việc đóng góp nó cho sách hướng dẫn Emacs Lisp không? –

4

Đây là một cách an toàn để kiểm tra khả năng 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))) 

Và đây là một cách để gửi thông báo 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

Hoặc, chỉ evalua Những điều sau đây trong Emacs:

(info "(dbus)") 
+1

Hoặc 'C-h i g (dbus) RET' – phils

Các vấn đề liên quan