2010-12-17 2 views

ответ

23

Я просто была такая же проблема и нашел Emacs-фу статью, которая приходит, когда прибегая к помощи немного слишком основной для моих потребностей.

В частности, я хотел экспортировать свои собственные методы elisp через dbus и имел проблемы с пониманием терминологии dbus и того, как она применяется к интерфейсу emacs dbus.

Первое, что нужно проверить, в документации Emacs, Ch F DBus-регистр-метод

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 только собирается быть: сеанс или: систему (где вы, вероятно, почти всегда нужно использовать: сеанс как и настольное приложение, я полагаю).

СЕРВИС - уникальное имя для приложения на шине, например, адрес или доменное имя. Dbus.el определяет dbus-service-emacs как «org.gnu.Emacs».

PATH относится к различным типам приложений, что SERVICE относится к различным приложениям. Например, определенный модуль emacs может раскрывать функциональные возможности в/PATH-модуле в службе org.gnu.Emacs SERVICE.

ИНТЕРФЕЙС - это как интерфейс в программировании. Это спецификация, которая сообщает другим клиентам 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»). Вы можете использовать его именно так и попытаться вызвать метод hello с помощью qdbus org.test.emacs /helloworld org.test.emacs.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) 
+0

Это должен быть главный ответ. –

+0

Это замечательно. Считаете ли вы способствующим это руководство Emacs Lisp? –

4

Вот безопасный способ проверить возможности 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

Или просто оцените т. е. в Emacs:

(info "(dbus)") 
+1

Или 'C-h i g (dbus) RET' – phils

 Смежные вопросы

  • Нет связанных вопросов^_^