Я искал пакет dbus и кажется, что все функции встроены в исходный код C, и для них нет документации.Как использовать интерфейс DBUS от Emacs?
Как использовать функцию dbus-call-method
?
Я искал пакет dbus и кажется, что все функции встроены в исходный код C, и для них нет документации.Как использовать интерфейс DBUS от Emacs?
Как использовать функцию dbus-call-method
?
Google на помощь ... Следуйте по ссылке для примера, это не мой код, поэтому я не стану его здесь.
http://emacs-fu.blogspot.com/2009/01/using-d-bus-example.html
Я просто была такая же проблема и нашел 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)
Вот безопасный способ проверить возможности 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 Lisp? –