为了学习DBUS,写的练习程序。修改了gtk指南中tictactoe的代码, tictactoe上有三行三列9个按键,三个连成行列或斜线的按钮被按下后则reset。在其中加入DBUS server,使其他程序可以通过DBUS控制tictactoe中的按键。
tictactoe.c中包含了tictactoe类定义,ttt_test.c中则创建了一个实例。
实现一个描述 object的XML文件,其中定义了interface和method, <?xml version="1.0" encoding="UTF-8" ?> <node name="/com/lp/tictactoe"> <interface name="com.lp.tictactoe"> <method name="keypad"> <arg type="u" name="x" direction="in" /> </method> </interface> </node> 并使用 dbus-binding-tool产生头文件dbus-binding-tool --mode=glib-server --prefix=tictactoe tictactoe.xml > tictactoe-glue2.h
调用 dbus_g_object_type_install_info函数安装 introspection信息,通常在 class_init中调用。
static void tictactoe_class_init (TictactoeClass *klass) { tictactoe_signals[TICTACTOE_SIGNAL] = g_signal_new ("tictactoe", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (TictactoeClass, tictactoe), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /* install GTYPE introspection info */ dbus_g_object_type_install_info(TICTACTOE_TYPE, &dbus_glib_tictactoe_object_info); }
定义函数,对应object中的方法,这里函数为tictactoe_keypad, 'keypad'在之前的XML文件中定义。gboolean tictactoe_keypad(Tictactoe *ttt, guint32 keynum, GError ** error) { int i, j; g_print("%d", keynum); if (keynum > 9 || keynum == 0) { g_print("%d: wrong number, should be 1-9.", keynum); return FALSE; } /* toggle the button associated with keynum */ i = (keynum - 1) / 3; j = (keynum - 1) % 3; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]), !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (ttt->buttons[i][j]))); return TRUE; }
调用 dbus_g_connection_register_g_object函数导出 object,这样改object将可以被连到同一个BUS上的其他程序所访问。connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if(connection == NULL) { g_printerr("Fialed to open connection to bus: %s/n", error->message); g_error_free(error); exit(1); } dbus_g_connection_register_g_object(connection, "/com/lp/tictactoe", ttt);
在tictactoe-client.c中实现了一个client,远程使用之前创建的 Object:
1.为 object创建一个 proxy proxy = dbus_g_proxy_new_for_name(connection, argv[1], "/com/lp/tictactoe", "com.lp.tictactoe");
2.调用方法,dbus_g_proxy_call(proxy, "keypad", &error, G_TYPE_UINT, atoi(argv[2]), G_TYPE_INVALID, G_TYPE_INVALID) 注意这里的方法名为'keypad'而非'tictactoe-keypad'。
使用如下命令 监视dbus。 dbus-monitor --session |grep -i hello
运行ttt-test,将会在监视时看到类似如下信息,method call sender=:1.165 -> dest=org.freedesktop.DBus serial=1 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=Hello 其中':1.165'部分即是ttt-test连接导DBUS上的unique address。
使用该命令即可向ttt-test发送按键信息,./tictactoe-client ADDR KEYNUM 比如,./tictactoe-client ":1.165" 5 中间的按键将被按下。
源码:https://github.com/largeplum/tictactoe