'\" t .TH "SD_BUS_ADD_OBJECT_VTABLE" "3" "" "systemd 244" "sd_bus_add_object_vtable" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" sd_bus_add_object_vtable, sd_bus_add_fallback_vtable, SD_BUS_VTABLE_START, SD_BUS_VTABLE_END, SD_BUS_METHOD_WITH_NAMES_OFFSET, SD_BUS_METHOD_WITH_NAMES, SD_BUS_METHOD_WITH_OFFSET, SD_BUS_METHOD, SD_BUS_SIGNAL_WITH_NAMES, SD_BUS_SIGNAL, SD_BUS_WRITABLE_PROPERTY, SD_BUS_PROPERTY, SD_BUS_PARAM \- Declare properties and methods for a D\-Bus path .SH "SYNOPSIS" .sp .ft B .nf #include .fi .ft .sp .HP \w'typedef\ int\ (*sd_bus_message_handler_t)('u .BI "typedef int (*sd_bus_message_handler_t)(sd_bus_message\ *" "m" ", void\ *" "userdata" ", sd_bus_error\ *" "ret_error" ");" .HP \w'typedef\ int\ (*sd_bus_property_get_t)('u .BI "typedef int (*sd_bus_property_get_t)(sd_bus\ *" "bus" ", const\ char\ *" "path" ", const\ char\ *" "interface" ", const\ char\ *" "property" ", sd_bus_message\ *" "reply" ", void\ *" "userdata" ", sd_bus_error\ *" "ret_error" ");" .HP \w'typedef\ int\ (*sd_bus_property_set_t)('u .BI "typedef int (*sd_bus_property_set_t)(sd_bus\ *" "bus" ", const\ char\ *" "path" ", const\ char\ *" "interface" ", const\ char\ *" "property" ", sd_bus_message\ *" "value" ", void\ *" "userdata" ", sd_bus_error\ *" "ret_error" ");" .HP \w'typedef\ int\ (*sd_bus_object_find_t)('u .BI "typedef int (*sd_bus_object_find_t)(const\ char\ *" "path" ", const\ char\ *" "interface" ", void\ *" "userdata" ", void\ **" "ret_found" ", sd_bus_error\ *" "ret_error" ");" .HP \w'int\ sd_bus_add_object_vtable('u .BI "int sd_bus_add_object_vtable(sd_bus\ *" "bus" ", sd_bus_slot\ **" "slot" ", const\ char\ *" "path" ", const\ char\ *" "interface" ", const\ sd_bus_vtable\ *" "vtable" ", void\ *" "userdata" ");" .HP \w'int\ sd_bus_add_fallback_vtable('u .BI "int sd_bus_add_fallback_vtable(sd_bus\ *" "bus" ", sd_bus_slot\ **" "slot" ", const\ char\ *" "prefix" ", const\ char\ *" "interface" ", const\ sd_bus_vtable\ *" "vtable" ", sd_bus_object_find_t\ " "find" ", void\ *" "userdata" ");" .PP \fBSD_BUS_VTABLE_START(\fR\fB\fIflags\fR\fR\fB)\fR .PP \fBSD_BUS_VTABLE_END\fR .PP \fBSD_BUS_METHOD_WITH_NAMES_OFFSET( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIin_names\fR\fR\fB, \fR\fB\fIresult\fR\fR\fB, \fR\fB\fIout_names\fR\fR\fB, \fR\fB\fIhandler\fR\fR\fB, \fR\fB\fIoffset\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_METHOD_WITH_NAMES( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIin_names\fR\fR\fB, \fR\fB\fIresult\fR\fR\fB, \fR\fB\fIout_names\fR\fR\fB, \fR\fB\fIhandler\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_METHOD_WITH_OFFSET( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIresult\fR\fR\fB, \fR\fB\fIhandler\fR\fR\fB, \fR\fB\fIoffset\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_METHOD( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIresult\fR\fR\fB, \fR\fB\fIhandler\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_SIGNAL_WITH_NAMES( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fInames\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_SIGNAL( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_WRITABLE_PROPERTY( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIget\fR\fR\fB, \fR\fB\fIset\fR\fR\fB, \fR\fB\fIoffset\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_PROPERTY( \fR\fB\fImember\fR\fR\fB, \fR\fB\fIsignature\fR\fR\fB, \fR\fB\fIget\fR\fR\fB, \fR\fB\fIoffset\fR\fR\fB, \fR\fB\fIflags\fR\fR\fB) \fR .PP \fBSD_BUS_PARAM(\fR\fB\fIname\fR\fR\fB)\fR .SH "DESCRIPTION" .PP \fBsd_bus_add_object_vtable()\fR is used to declare attributes for the path object path \fIpath\fR connected to the bus connection \fIbus\fR under the interface \fIinterface\fR\&. The table \fIvtable\fR may contain property declarations using \fBSD_BUS_PROPERTY()\fR or \fBSD_BUS_WRITABLE_PROPERTY()\fR, method declarations using \fBSD_BUS_METHOD()\fR, \fBSD_BUS_METHOD_WITH_NAMES()\fR, \fBSD_BUS_METHOD_WITH_OFFSET()\fR, or \fBSD_BUS_METHOD_WITH_NAMES_OFFSET()\fR, and signal declarations using \fBSD_BUS_SIGNAL_WITH_NAMES()\fR or \fBSD_BUS_SIGNAL()\fR, see below\&. The \fIuserdata\fR parameter contains a pointer that will be passed to various callback functions\&. It may be specified as \fBNULL\fR if no value is necessary\&. .PP \fBsd_bus_add_fallback_vtable()\fR is similar to \fBsd_bus_add_object_vtable()\fR, but is used to register "fallback" attributes\&. When looking for an attribute declaration, bus object paths registered with \fBsd_bus_add_object_vtable()\fR are checked first\&. If no match is found, the fallback vtables are checked for each prefix of the bus object path, i\&.e\&. with the last slash\-separated components successively removed\&. This allows the vtable to be used for an arbitrary number of dynamically created objects\&. .PP Parameter \fIfind\fR is a function which is used to locate the target object based on the bus object path \fIpath\fR\&. It must return \fB1\fR and set the \fIret_found\fR output parameter if the object is found, return \fB0\fR if the object was not found, and return a negative errno\-style error code or initialize the error structure \fIret_error\fR on error\&. The pointer passed in \fIret_found\fR will be used as the \fIuserdata\fR parameter for the callback functions (offset by the \fIoffset\fR offsets as specified in the vtable entries)\&. .PP For both functions, a match slot is created internally\&. If the output parameter \fIslot\fR is \fBNULL\fR, a "floating" slot object is created, see \fBsd_bus_slot_set_floating\fR(3)\&. Otherwise, a pointer to the slot object is returned\&. In that case, the reference to the slot object should be dropped when the vtable is not needed anymore, see \fBsd_bus_slot_unref\fR(3)\&. .SS "The sd_bus_vtable array" .PP The array consists of the structures of type sd_bus_vtable, but it should never be filled in manually, but through one of the following macros: .PP \fBSD_BUS_VTABLE_START()\fR, \fBSD_BUS_VTABLE_END\fR .RS 4 Those must always be the first and last element\&. .RE .PP \fBSD_BUS_METHOD_WITH_NAMES_OFFSET()\fR, \fBSD_BUS_METHOD_WITH_NAMES()\fR, \fBSD_BUS_METHOD_WITH_OFFSET()\fR, \fBSD_BUS_METHOD()\fR .RS 4 Declare a D\-Bus method with the name \fImember\fR, parameter signature \fIsignature\fR, result signature \fIresult\fR\&. Parameters \fIin_names\fR and \fIout_names\fR specify the argument names of the input and output arguments in the function signature\&. The handler function \fIhandler\fR must be of type \fBsd_bus_message_handler_t\fR\&. It will be called to handle the incoming messages that call this method\&. It receives a pointer that is the \fIuserdata\fR parameter passed to the registration function offset by \fIoffset\fR bytes\&. This may be used to pass pointers to different fields in the same data structure to different methods in the same vtable\&. \fIin_names\fR and \fIout_names\fR should be created using the \fBSD_BUS_PARAM()\fR macro, see below\&. Parameter \fIflags\fR is a combination of flags, see below\&. .sp \fBSD_BUS_METHOD_WITH_NAMES()\fR, \fBSD_BUS_METHOD_WITH_OFFSET()\fR, and \fBSD_BUS_METHOD()\fR are variants which specify zero offset (\fIuserdata\fR parameter is passed with no change), leave the names unset (i\&.e\&. no parameter names), or both\&. .RE .PP \fBSD_BUS_SIGNAL_WITH_NAMES()\fR, \fBSD_BUS_SIGNAL()\fR .RS 4 Declare a D\-Bus signal with the name \fImember\fR, parameter signature \fIsignature\fR, and argument names \fInames\fR\&. \fInames\fR should be created using the \fBSD_BUS_PARAM()\fR macro, see below\&. Parameter \fIflags\fR is a combination of flags, see below\&. .sp Equivalent to \fBSD_BUS_SIGNAL_WITH_NAMES()\fR with the \fInames\fR parameter unset (i\&.e\&. no parameter names)\&. .RE .PP \fBSD_BUS_WRITABLE_PROPERTY()\fR, \fBSD_BUS_PROPERTY()\fR .RS 4 Declare a D\-Bus property with the name \fImember\fR and value signature \fIsignature\fR\&. Parameters \fIget\fR and \fIset\fR are the getter and setter methods\&. They are called with a pointer that is the \fIuserdata\fR parameter passed to the registration function offset by \fIoffset\fR bytes\&. This may be used pass pointers to different fields in the same data structure to different setters and getters in the same vtable\&. Parameter \fIflags\fR is a combination of flags, see below\&. .sp The setter and getter methods may be omitted (specified as \fBNULL\fR), if the property has one of the basic types or "as" in case of read\-only properties\&. In those cases, the \fIuserdata\fR and \fIoffset\fR parameters must together point to valid variable of the corresponding type\&. A default setter and getters will be provided, which simply copy the argument between this variable and the message\&. .sp \fBSD_BUS_PROPERTY()\fR is used to define a read\-only property\&. .RE .PP \fBSD_BUS_PARAM()\fR .RS 4 Parameter names should be wrapped in this macro, see the example below\&. .RE .SS "Flags" .PP The \fIflags\fR parameter is used to specify a combination of \m[blue]\fBD\-Bus annotations\fR\m[]\&\s-2\u[1]\d\s+2\&. .PP \fBSD_BUS_VTABLE_DEPRECATED\fR .RS 4 Mark this vtable entry as deprecated using the \fBorg\&.freedesktop\&.DBus\&.Deprecated\fR annotation in introspection data\&. If specified for \fBSD_BUS_VTABLE_START()\fR, the annotation is applied to the enclosing interface\&. .RE .PP \fBSD_BUS_VTABLE_HIDDEN\fR .RS 4 Make this vtable entry hidden\&. It will not be shown in introspection data\&. If specified for \fBSD_BUS_VTABLE_START()\fR, all entries in the array are hidden\&. .RE .PP \fBSD_BUS_VTABLE_UNPRIVILEGED\fR .RS 4 Mark this vtable entry as unprivileged\&. If not specified, the \fBorg\&.freedesktop\&.systemd1\&.Privileged\fR annotation with value "true" will be shown in introspection data\&. .RE .PP \fBSD_BUS_VTABLE_METHOD_NO_REPLY\fR .RS 4 Mark his vtable entry as a method that will not return a reply using the \fBorg\&.freedesktop\&.DBus\&.Method\&.NoReply\fR annotation in introspection data\&. .RE .PP \fBSD_BUS_VTABLE_PROPERTY_CONST\fR, \fBSD_BUS_VTABLE_PROPERTY_EMITS_CHANGE\fR, \fBSD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION\fR .RS 4 Those three flags correspond to different values of the \fBorg\&.freedesktop\&.DBus\&.Property\&.EmitsChangedSignal\fR annotation, which specifies whether the \fBorg\&.freedesktop\&.DBus\&.Properties\&.PropertiesChanged\fR signal is emitted whenever the property changes\&. \fBSD_BUS_VTABLE_PROPERTY_CONST\fR corresponds to \fBconst\fR and means that the property never changes during the lifetime of the object it belongs to, so no signal needs to be emitted\&. \fBSD_BUS_VTABLE_PROPERTY_EMITS_CHANGE\fR corresponds to \fBtrue\fR and means that the signal is emitted\&. \fBSD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION\fR corresponds to \fBinvalidates\fR and means that the signal is emitted, but the value is not included in the signal\&. .RE .PP \fBSD_BUS_VTABLE_PROPERTY_EXPLICIT\fR .RS 4 Mark this vtable property entry as requiring explicit request to for the value to be shown (generally because the value is large or slow to calculate)\&. This entry cannot be combined with \fBSD_BUS_VTABLE_PROPERTY_EMITS_CHANGE\fR, and will not be shown in property listings by default (e\&.g\&. \fBbusctl introspect\fR)\&. This corresponds to the \fBorg\&.freedesktop\&.systemd1\&.Explicit\fR annotation in introspection data\&. .RE .SH "EXAMPLES" .PP \fBExample\ \&1.\ \&Create a simple listener on the bus\fR .sp .if n \{\ .RS 4 .\} .nf #include #include #include #include #include #include #define _cleanup_(f) __attribute__((cleanup(f))) typedef struct object { char *name; uint32_t number; } object; static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) { printf("Got called with userdata=%p\en", userdata); return 1; } static const sd_bus_vtable vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_METHOD( "Method1", "s", "s", method, 0), SD_BUS_METHOD_WITH_NAMES_OFFSET( "Method2", "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path), "s", SD_BUS_PARAM(returnstring), method, offsetof(object, number), SD_BUS_VTABLE_DEPRECATED), SD_BUS_WRITABLE_PROPERTY( "AutomaticStringProperty", "s", NULL, NULL, offsetof(object, name), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_WRITABLE_PROPERTY( "AutomaticIntegerProperty", "u", NULL, NULL, offsetof(object, number), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_VTABLE_END }; #define check(x) ({ \e int r = x; \e errno = r < 0 ? \-r : 0; \e printf(#x ": %m\en"); \e if (r < 0) \e return EXIT_FAILURE; \e }) int main(int argc, char **argv) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; sd_bus_default(&bus); object object = { \&.number = 666 }; check((object\&.name = strdup("name")) != NULL); check(sd_bus_add_object_vtable(bus, NULL, "/object", "org\&.freedesktop\&.systemd\&.VtableExample", vtable, &object)); for (;;) { check(sd_bus_wait(bus, UINT64_MAX)); check(sd_bus_process(bus, NULL)); } free(object\&.name); return 0; } .fi .if n \{\ .RE .\} .PP This creates a simple client on the bus (the user bus, when run as normal user)\&. We may use the D\-Bus \fBorg\&.freedesktop\&.DBus\&.Introspectable\&.Introspect\fR call to acquire the XML description of the interface: .sp .if n \{\ .RS 4 .\} .nf .fi .if n \{\ .RE .\} .SH "RETURN VALUE" .PP On success, \fBsd_bus_add_object_vtable\fR and \fBsd_bus_add_fallback_vtable\fR calls return 0 or a positive integer\&. On failure, they return a negative errno\-style error code\&. .SS "Errors" .PP Returned errors may indicate the following problems: .PP \fB\-EINVAL\fR .RS 4 One of the required parameters is \fBNULL\fR or invalid\&. A reserved D\-Bus interface was passed as the \fIinterface\fR parameter\&. .RE .PP \fB\-ENOPKG\fR .RS 4 The bus cannot be resolved\&. .RE .PP \fB\-ECHILD\fR .RS 4 The bus was created in a different process\&. .RE .PP \fB\-ENOMEM\fR .RS 4 Memory allocation failed\&. .RE .PP \fB\-EPROTOTYPE\fR .RS 4 \fBsd_bus_add_object_vtable\fR and \fBsd_bus_add_fallback_vtable\fR have been both called for the same bus object path, which is not allowed\&. .RE .PP \fB\-EEXIST\fR .RS 4 This vtable has already been registered for this \fIinterface\fR and \fIpath\fR\&. .RE .SH "NOTES" .PP These APIs are implemented as a shared library, which can be compiled and linked to with the \fBlibsystemd\fR\ \&\fBpkg-config\fR(1) file\&. .SH "SEE ALSO" .PP \fBsd-bus\fR(3), \fBbusctl\fR(1) .SH "NOTES" .IP " 1." 4 D-Bus annotations .RS 4 \%https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format .RE