dbus双方向通信例cコード

9656 ワード

ネット上の大部分は一方向転送の例しかなく、双方向通信はbusname、interface、pathなどの付与に少しこだわっている.そうしないと、初期化に失敗したり、送受信できなかったりしやすい.ソースコードは以下の通りである.
#include 
#include 
#include 
#include 
#include 
#include 

struct DBus
{
    char m_receiverBusName[64];
    char m_receiverPath[32];
    char m_receiverInterFace[32];
    char m_receiverMethod[16];
    char m_sendBusName[64];
};

DBusConnection * DbusInit(const char *name, DBusError *perr)
{
    int ret;
    DBusError &err = *perr;
    DBusConnection *connection;

    pid_t pid;
    pid = getpid();

    dbus_error_init(&err);
    //    session D-Bus   
    connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
    if (!connection)
    {
        if (dbus_error_is_set(&err))
            printf("Connection Error %s
", err.message); else printf("%s %d err
", __func__, __LINE__); return NULL; } // printf("init PID = %d, name = %s
", pid, name); ret = dbus_bus_request_name(connection, name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { if (dbus_error_is_set(&err)) printf("Name Error %s
", err.message); else printf("%s %d err
", __func__, __LINE__); return NULL; } // disconnect (_exit()) dbus_connection_set_exit_on_disconnect(connection, false); return connection; } void ReplyMethodCall(DBusMessage *msg, DBusConnection *conn) { DBusMessageIter msg_arg; // msg , if (!dbus_message_iter_init(msg, &msg_arg)) { printf("Message has NO Argument
"); return; } do { int ret = dbus_message_iter_get_arg_type(&msg_arg); if (DBUS_TYPE_STRING == ret) { char *pdata; dbus_message_iter_get_basic(&msg_arg, &pdata); printf("get Method Argument STRING: %s
", pdata); } else { printf("Argument Type ERROR
"); } } while (dbus_message_iter_next(&msg_arg)); dbus_connection_flush(conn); } /* D-Bus , */ //void DbusReceive(DBusConnection *connection) void * ReceiveThread(void *arg) { struct DBus *dbus = (struct DBus *)arg; DBusError err; DBusConnection *connection = DbusInit(dbus->m_receiverBusName, &err); if (connection == NULL) { dbus_error_free(&err); return NULL; } printf("ReceiveThread %s, %s, %s, %s
", dbus->m_receiverBusName, dbus->m_receiverPath, dbus->m_receiverInterFace, dbus->m_receiverMethod); DBusMessage *msg; while (1) { dbus_connection_read_write(connection, 0); msg = dbus_connection_pop_message(connection); if (msg == NULL) { sleep(1); continue; } const char *path = dbus_message_get_path(msg); if (path == NULL || strcmp(path, dbus->m_receiverPath)) { printf("Wrong PATH: %s !=%s
", (path==NULL ? "" : path), dbus->m_receiverPath); dbus_message_unref(msg); continue; } printf("Get a Message
"); if (dbus_message_is_method_call(msg, dbus->m_receiverInterFace, dbus->m_receiverMethod)) { printf("Someone Call My Method
"); ReplyMethodCall(msg, connection); } else { printf("NOT a Signal OR a Method
"); } dbus_message_unref(msg); } dbus_error_free(&err); } static void DbusSend(struct DBus *dbus, DBusConnection *connection, const void *value) { printf("DbusSend %s, %s, %s, %s
", dbus->m_receiverBusName, dbus->m_receiverPath, dbus->m_receiverInterFace, dbus->m_receiverMethod); // , method call 。 //Constructs a new message to invoke a method on a remote object. DBusMessage *msg = dbus_message_new_method_call( dbus->m_receiverBusName, dbus->m_receiverPath, dbus->m_receiverInterFace, dbus->m_receiverMethod); if (msg == NULL) { printf("Message NULL"); return; } DBusMessageIter arg; dbus_message_iter_init_append(msg, &arg); if (!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &value)) { printf("Out of Memory!"); dbus_message_unref(msg); return; } // reply handle 。Queues a message to send, as with dbus_connection_send() // but also returns a DBusPendingCall used to receive a reply to the message. DBusPendingCall *pending; if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) { printf("Out of Memory!"); dbus_message_unref(msg); return; } if (pending == NULL) { printf("Pending Call NULL: connection is disconnected "); dbus_message_unref(msg); return; } dbus_connection_flush(connection); dbus_message_unref(msg); } int main(int argc, char *argv[]) { if (strncmp(argv[1], "1", 1) == 0) { struct DBus rdbus; strcpy(rdbus.m_receiverBusName, "com.bt.c2s"); strcpy(rdbus.m_receiverPath, "/com/bt/c2s/object"); strcpy(rdbus.m_receiverInterFace, "com.bt.c2s.interface"); strcpy(rdbus.m_receiverMethod,"method"); strcpy(rdbus.m_sendBusName, ""); pthread_t thread; pthread_create(&thread, NULL, ReceiveThread, &rdbus); struct DBus wdbus; strcpy(wdbus.m_receiverBusName, "com.bt.s2c"); strcpy(wdbus.m_receiverPath, "/com/bt/s2c/object"); strcpy(wdbus.m_receiverInterFace, "com.bt.s2c.interface"); strcpy(wdbus.m_receiverMethod,"method"); strcpy(wdbus.m_sendBusName, "com.bt.s2c_send"); DBusError err; DBusConnection *connection = DbusInit(wdbus.m_sendBusName, &err); if (connection == NULL) { printf("%s %d
", __func__, __LINE__); dbus_error_free(&err); return -1; } while (1) { DbusSend(&wdbus, connection, "world"); sleep(3); } dbus_error_free(&err); } else if (strncmp(argv[1], "2", 1) == 0) { struct DBus rdbus; strcpy(rdbus.m_receiverBusName, "com.bt.s2c"); strcpy(rdbus.m_receiverPath, "/com/bt/s2c/object"); strcpy(rdbus.m_receiverInterFace, "com.bt.s2c.interface"); strcpy(rdbus.m_receiverMethod,"method"); strcpy(rdbus.m_sendBusName, ""); pthread_t thread; pthread_create(&thread, NULL, ReceiveThread, &rdbus); struct DBus wdbus; strcpy(wdbus.m_receiverBusName, "com.bt.c2s"); strcpy(wdbus.m_receiverPath, "/com/bt/c2s/object"); strcpy(wdbus.m_receiverInterFace, "com.bt.c2s.interface"); strcpy(wdbus.m_receiverMethod,"method"); strcpy(wdbus.m_sendBusName, "com.bt.c2s_send"); DBusError err; DBusConnection *connection = DbusInit(wdbus.m_sendBusName, &err); if (connection == NULL) { printf("%s %d
", __func__, __LINE__); dbus_error_free(&err); return -1; } while (1) { DbusSend(&wdbus, connection, "hello"); sleep(3); } dbus_error_free(&err); } printf("%s %d
", __func__, __LINE__); return 0; }

コンパイル:g++test.cpp `pkg-config --cflags --libs dbus-1` -lpthread
テストの実行:
一端、一線読み、もう一つのスレッドはwordを送信します.反対側は、一線で読み、別のスレッドはhelloを送信します.
./a.out 1 init PID = 20744, name = com.bt.s2c_send init PID = 20744, name = com.bt.c2s DbusSend com.bt.s2c,/com/bt/s2c/object, com.bt.s2c.interface, method ReceiveThread com.bt.c2s,/com/bt/c2s/object, com.bt.c2s.interface, method Wrong PATH:/org/freedesktop/DBus !=/com/bt/c2s/object Wrong PATH:/org/freedesktop/DBus !=/com/bt/c2s/object Wrong PATH:/org/freedesktop/DBus !=/com/bt/c2s/object Wrong PATH:  !=/com/bt/c2s/object DbusSend com.bt.s2c,/com/bt/s2c/object, com.bt.s2c.interface, method Wrong PATH:  !=/com/bt/c2s/object Get a Message Someone Call My Method get Method Argument STRING: hello DbusSend com.bt.s2c,/com/bt/s2c/object, com.bt.s2c.interface, method Get a Message Someone Call My Method get Method Argument STRING: hello
 
./a.out 2 init PID = 20746, name = com.bt.c2s_send init PID = 20746, name = com.bt.s2c ReceiveThread com.bt.s2c,/com/bt/s2c/object, com.bt.s2c.interface, method DbusSend com.bt.c2s,/com/bt/c2s/object, com.bt.c2s.interface, method Wrong PATH:/org/freedesktop/DBus !=/com/bt/s2c/object Wrong PATH:/org/freedesktop/DBus !=/com/bt/s2c/object Wrong PATH:/org/freedesktop/DBus !=/com/bt/s2c/object DbusSend com.bt.c2s,/com/bt/c2s/object, com.bt.c2s.interface, method Get a Message Someone Call My Method get Method Argument STRING: world DbusSend com.bt.c2s,/com/bt/c2s/object, com.bt.c2s.interface,method Get a Message Someone Call My Method get Method Argument STRING:world作者:かっこよくて外出できない