程式語言 - GNU - C/C++ - D-Bus(sd-bus)



參考資訊:
https://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html
https://www.freedesktop.org/software/systemd/man/latest/sd_bus_message_read.html

main.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <systemd/sd-bus.h>

static int method_test(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
    int64_t x = 0;
    int64_t y = 0;

    sd_bus_message_read(m, "xx", &x, &y);
    return sd_bus_reply_method_return(m, "x", x * y);
}

static const sd_bus_vtable vtable[] = {
    SD_BUS_VTABLE_START(0),
    SD_BUS_METHOD("Test", "xx", "x", method_test, SD_BUS_VTABLE_UNPRIVILEGED),
    SD_BUS_VTABLE_END
};

int main(int argc, char *argv[])
{
    sd_bus *bus = NULL;
    sd_bus_slot *slot = NULL;

    sd_bus_open_user(&bus);
    sd_bus_add_object_vtable(bus, &slot,
        "/fake/mytest/test",
        "fake.mytest.test",
        vtable,
        NULL
    );
    sd_bus_request_name(bus, "fake.mytest.test.service", 0);

    for (;;) {
        sd_bus_process(bus, NULL);
        sd_bus_wait(bus, -1);
    }

    sd_bus_slot_unref(slot);
    sd_bus_unref(bus);

    return 0;
}

編譯、執行

$ gcc main.c -o test `pkg-config --cflags --libs libsystemd`
$ ./test

測試

$ busctl --user tree fake.mytest.test.service
└─/fake
  └─/fake/mytest
    └─/fake/mytest/test

$ busctl --user introspect fake.mytest.test.service /fake/mytest/test
    NAME                                TYPE      SIGNATURE RESULT/VALUE FLAGS
    fake.mytest.test                    interface -         -            -
    .Test                               method    xx        x            -
    org.freedesktop.DBus.Introspectable interface -         -            -
    .Introspect                         method    -         s            -
    org.freedesktop.DBus.Peer           interface -         -            -
    .GetMachineId                       method    -         s            -
    .Ping                               method    -         -            -
    org.freedesktop.DBus.Properties     interface -         -            -
    .Get                                method    ss        v            -
    .GetAll                             method    s         a{sv}        -
    .Set                                method    ssv       -            -
    .PropertiesChanged                  signal    sa{sv}as  -            -

$ busctl --user call fake.mytest.test.service /fake/mytest/test fake.mytest.test Test xx 3 5
    x 15