dbus: Type Conversion
3 Mapping Lisp types and D-Bus types.
*************************************
D-Bus method calls and signals accept usually several arguments as
parameters, either as input parameter, or as output parameter. Every
argument belongs to a D-Bus type.
Such arguments must be mapped between the value encoded as a D-Bus
type, and the corresponding type of Lisp objects. The mapping is
applied Lisp object ↦ D-Bus type for input parameters, and D-Bus type ↦
Lisp object for output parameters.
3.1 Input parameters.
=====================
Input parameters for D-Bus methods and signals occur as arguments of a
Lisp function call. The following mapping to D-Bus types is applied,
when the corresponding D-Bus message is created:
Lisp type D-Bus type
t and nil ↦ DBUS_TYPE_BOOLEAN
natural number ↦ DBUS_TYPE_UINT32
negative integer ↦ DBUS_TYPE_INT32
float ↦ DBUS_TYPE_DOUBLE
string ↦ DBUS_TYPE_STRING
list ↦ DBUS_TYPE_ARRAY
Other Lisp objects, like symbols or hash tables, are not accepted as
input parameters.
If it is necessary to use another D-Bus type, a corresponding type
symbol can be prepended to the corresponding Lisp object. Basic D-Bus
types are represented by the type symbols ‘:byte’, ‘:boolean’, ‘:int16’,
‘:uint16’, ‘:int32’, ‘:uint32’, ‘:int64’, ‘:uint64’, ‘:double’,
‘:string’, ‘:object-path’, ‘:signature’ and ‘:unix-fd’.
Example:
(dbus-call-method ... NAT-NUMBER STRING)
is equivalent to
(dbus-call-method ... :uint32 NAT-NUMBER :string STRING)
but different to
(dbus-call-method ... :int32 NAT-NUMBER :signature STRING)
The value for a byte D-Bus type can be any integer in the range 0
through 255. If a character is used as argument, modifiers represented
outside this range are stripped of. For example, ‘:byte ?x’ is equal to
‘:byte ?\M-x’, but it is not equal to ‘:byte ?\C-x’ or ‘:byte ?\M-\C-x’.
Signed and unsigned integer D-Bus types expect a corresponding
integer value. If the value does not fit Emacs’s integer range, it is
also possible to use an equivalent floating point number.
A D-Bus compound type is always represented as a list. The CAR of
this list can be the type symbol ‘:array’, ‘:variant’, ‘:struct’ or
‘:dict-entry’, which would result in a corresponding D-Bus container.
‘:array’ is optional, because this is the default compound D-Bus type
for a list.
The objects being elements of the list are checked according to the
D-Bus compound type rules.
• An array must contain only elements of the same D-Bus type. It can
be empty.
• A variant must contain only one single element.
• A dictionary entry must be element of an array, and it must contain
only a key-value pair of two elements, with a basic D-Bus type key.
• There is no restriction for structs.
If an empty array needs an element D-Bus type other than string, it
can contain exactly one element of D-Bus type ‘:signature’. The value
of this element (a string) is used as the signature of the elements of
this array. Example:
(dbus-call-method
:session "org.freedesktop.Notifications"
"/org/freedesktop/Notifications"
"org.freedesktop.Notifications" "Notify"
"GNU Emacs" ;; Application name.
0 ;; No replacement of other notifications.
"" ;; No icon.
"Notification summary" ;; Summary.
(format ;; Body.
"This is a test notification, raised from\n%S" (emacs-version))
'(:array) ;; No actions (empty array of strings).
'(:array :signature "{sv}") ;; No hints
;; (empty array of dictionary entries).
:int32 -1) ;; Default timeout.
⇒ 3
-- Function: dbus-string-to-byte-array string
Sometimes, D-Bus methods require as input parameter an array of
bytes, instead of a string. If it is guaranteed, that STRING is an
UTF8 string, this function performs the conversion. Example:
(dbus-string-to-byte-array "/etc/hosts")
⇒ (:array :byte 47 :byte 101 :byte 116 :byte 99 :byte 47
:byte 104 :byte 111 :byte 115 :byte 116 :byte 115)
-- Function: dbus-escape-as-identifier string
Escape an arbitrary STRING so it follows the rules for a C
identifier. The escaped string can be used as object path
component, interface element component, bus name component or
member name in D-Bus.
The escaping consists of replacing all non-alphanumerics, and the
first character if it’s a digit, with an underscore and two
lower-case hex digits. As a special case, "" is escaped to "_".
Example:
(dbus-escape-as-identifier "0123abc_xyz\x01\xff")
⇒ "_30123abc_5fxyz_01_ff"
3.2 Output parameters.
======================
Output parameters of D-Bus methods and signals are mapped to Lisp
objects.
D-Bus type Lisp type
DBUS_TYPE_BOOLEAN ↦ t or nil
DBUS_TYPE_BYTE ↦ natural number
DBUS_TYPE_UINT16 ↦ natural number
DBUS_TYPE_INT16 ↦ integer
DBUS_TYPE_UINT32 ↦ natural number or float
DBUS_TYPE_UNIX_FD ↦ natural number or float
DBUS_TYPE_INT32 ↦ integer or float
DBUS_TYPE_UINT64 ↦ natural number or float
DBUS_TYPE_INT64 ↦ integer or float
DBUS_TYPE_DOUBLE ↦ float
DBUS_TYPE_STRING ↦ string
DBUS_TYPE_OBJECT_PATH ↦ string
DBUS_TYPE_SIGNATURE ↦ string
DBUS_TYPE_ARRAY ↦ list
DBUS_TYPE_VARIANT ↦ list
DBUS_TYPE_STRUCT ↦ list
DBUS_TYPE_DICT_ENTRY ↦ list
A float object in case of ‘DBUS_TYPE_UINT32’, ‘DBUS_TYPE_INT32’,
‘DBUS_TYPE_UINT64’, ‘DBUS_TYPE_INT64’ and ‘DBUS_TYPE_UNIX_FD’ is
returned, when the C value exceeds the Emacs number size range.
The resulting list of the last 4 D-Bus compound types contains as
elements the elements of the D-Bus container, mapped according to the
same rules.
The signal ‘PropertyModified’, discussed as example in
Inspection, would offer as Lisp data the following object (BOOL stands
here for either ‘nil’ or ‘t’):
(INTEGER ((STRING BOOL BOOL) (STRING BOOL BOOL) ...))
-- Function: dbus-byte-array-to-string byte-array &optional multibyte
If a D-Bus method or signal returns an array of bytes, which are
known to represent an UTF8 string, this function converts
BYTE-ARRAY to the corresponding string. The string is unibyte
encoded, unless MULTIBYTE is non-‘nil’. Example:
(dbus-byte-array-to-string '(47 101 116 99 47 104 111 115 116 115))
⇒ "/etc/hosts"
-- Function: dbus-unescape-from-identifier string
Retrieve the original string from the encoded STRING as unibyte
string. STRING must have been encoded with
‘dbus-escape-as-identifier’. Example:
(dbus-unescape-from-identifier "_30123abc_5fxyz_01_ff")
⇒ "0123abc_xyz\x01\xff"
If the original string used in ‘dbus-escape-as-identifier’ is a
multibyte string, it cannot be expected that this function returns
that string:
(string-equal
(dbus-unescape-from-identifier
(dbus-escape-as-identifier "Grüß Göttin"))
"Grüß Göttin")
⇒ nil