2017-04-22 31 views
1

하위 레벨 DBus C 라이브러리를 사용하여 StatusNotifierWatcher 서비스를 구현하려고합니다. StatusNotifierWatcher 사양에서는 워커가 "StatusNotifierItem 인스턴스가 버스에서 사라진 시점"을 알 수 있어야하므로 StatusNotifierItemUnregistered 신호를 보낼 수 있습니다.DBus : 버스에서 이름이 사라질 때 조심하십시오

예도 구현 : 이름이 버스에서 사라지면

#include <stdio.h> 
#include <stdlib.h> 
#include <dbus/dbus.h> 

DBusConnection *conn = NULL; 

void item_unregistered_signal(const char *name) { 
    DBusMessage *signal = dbus_message_new_signal(
      "/org/freedesktop/StatusNotifierWatcher", 
      "org.freedesktop.StatusNotifierWatcher", 
      "StatusNotifierItemUnregistered"); 
    dbus_message_append_args(signal, 
      DBUS_TYPE_STRING, &name, 
      DBUS_TYPE_INVALID); 
    dbus_connection_send(conn, signal, NULL); 
    dbus_message_unref(signal); 
} 

void watch_name(const char *name, void(*cb)(const char *)) { 
    // Not sure how to impliment 
} 

dbus_bool_t register_item(DBusConnection *connection, DBusMessage *message, void *_data) { 
    DBusError error; 
    char *name; 

    if (!dbus_message_get_args(message, &error, 
       DBUS_TYPE_STRING, &name, 
       DBUS_TYPE_INVALID)) { 
     fprintf(stderr, "Error parsing method args: %s\n", error.message); 
     return FALSE; 
    } 

    watch_name(name, item_unregistered_signal); 
    return TRUE; 
} 

static void check_and_abort(DBusError *error) { 
    if (dbus_error_is_set(error)) { 
     fprintf(stderr, "dbus_err: %s\n", error->message); 
     exit(EXIT_FAILURE); 
    } 
} 

int main() { 
    DBusError error; 
    dbus_error_init(&error); 
    conn = dbus_bus_get(DBUS_BUS_SESSION, &error); 
    check_and_abort(&error); 

    dbus_bus_request_name(conn, "org.freedesktop.StatusNotifierWatcher", 
      DBUS_NAME_FLAG_REPLACE_EXISTING, 
      &error); 
    check_and_abort(&error); 

    dbus_connection_add_filter(conn, register_item, NULL, free); 

    while(1) { 
     dbus_connection_read_write_dispatch(conn, 1000); 
    } 
} 

나는 DBUS 서비스로 잘 알려진 이름이있는 경우는 어떻게 알 수 있습니까?

답변

1

글쎄, 나는 이것을 알아 냈고 libdbus로 작업해야하는 미래의 불쌍한 영혼들에 대한 답변을 게시 할 것입니다.

org.freedesktop.DBus은 DBus 이름이 변경 될 때마다 NameOwnerChanged 신호를 보냅니다. NewOwner 인수가 null 문자열이기 때문에이 신호를 사용하여 항목이 사라 졌는지 추적 할 수 있습니다. 이 기능은 작업을 수행 할 수 있습니다

static DBusHandlerResult signal_handler(DBusConnection *connection, 
     DBusMessage *message, void *_usr_data) { 

    if (dbus_message_is_signal(message, "org.freedesktop.DBus", 
      "NameOwnerChanged")) { 
     const char *name; 
     const char *old_owner; 
     const char *new_owner; 

     if (!dbus_message_get_args(message, NULL, 
       DBUS_TYPE_STRING, &name, 
       DBUS_TYPE_STRING, &old_owner, 
       DBUS_TYPE_STRING, &new_owner, 
       DBUS_TYPE_INVALID)) { 
      fprintf(stderr, "Error getting OwnerChanged args"); 
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 
     } 
     if (strcmp(name, "") != 0) { 
      // Name not lost, just swapped owners 
      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 
     } 
     name_lost(name); 
     return DBUS_HANDLER_RESULT_HANDLED; 
    } 
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 
} 

하나는 당신의 프로그램이 신호를 호출 할 수 있도록 일치하는 항목을 추가 할 필요가있다. 나는 상응하는 g_bus_watch_name()입니다 대신 libdbus가의 (실망) (권장) GDBus를 사용하는 사람들을 위해

dbus_bus_add_match(conn, 
     "type='signal',\ 
     sender='org.freedesktop.DBus',\ 
     interface='org.freedesktop.DBus',\ 
     member='NameOwnerChanged'", 
     &error); 
check_and_abort(&error); 

dbus_connection_add_filter(conn, signal_handler, NULL, free); 
0

main()이 추가되었습니다.

+0

libdbus는 가치가 없으므로 대부분의 경우 권장되지 않습니다. 사실, 다른 라이브러리보다 dbus 스펙에 맞춰져있을 가능성이 높습니다. 추가해 주셔서 감사합니다. 더 높은 수준의 라이브러리가이를위한 convinience 기능을 가지고 있음을 분명히하는 것이 좋습니다. – 4e554c4c

+0

죄송합니다, 당신 말이 맞습니다; 고도로 사용되지 않는 dbus-glib입니다. libdbus는 더 이상 사용되지 않지만 사용은 권장되지 않습니다. sd-bus는 일반적으로 낮은 수준의 D 버스 사용을위한 더 나은 대안으로 받아 들여집니다. 내 대답을 편집 할게. –

+0

누구에게 일반적으로 허용됩니까? 필자는 libdbus-1을 2 주 동안 사용해 왔으며 가장 가벼운 DBus 구현이라는 것을 알게되었습니다. 또한 libdbus-1이 가장 이해하기 쉽습니다. sd-dbus는 더 많은 의존성을 가지고 있으며, 일부 시스템은 systemd조차 갖고 있지 않습니다. –