日期:2014-05-16  浏览次数:20655 次

X 如何高效率的使用DBUS作client/server架构

引用自:

http://blog.csdn.net/cuijpus/archive/2007/12/07/1922658.aspx

?

?

在嵌入式系统中使用dbus主要有两个方面的用途:
1:进程间通信
2:实现client/server模式;

2也是1的具体表现形式;

包括dbus自带的例子,都是采用dbus对数据的封装,实现client/server模式的,
缺点有二:
1 一个API要定义一个xml接口描述
2 数据封装非常复杂,非常不利于以后接口的扩展;

为了客服上面的缺点,提高可扩展性和效率,可以这样做:
如果一个应用分为client,server两端的话,要高效率的实现client/server之间
的通信,可以采用如下方式:


第一步:定义一个通用的API xml 接口描述,暂命令为dbus_general.xml

<?xml version="1.0" encoding="UTF-8" ?>
<node name="/org/freedesktop/DBus/General_api">
? <interface name="org.freedesktop.DBus.general_api">
??? <method name="client_request">
????? <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="__client_request_cb"/>
????? <arg type="i" name="action_id" direction="in" />???//这个地方就是不同API的ID
????? <arg type="i" name="input_int" direction="in" />???//这个参数可以用,也可以不用
?? <arg type="ay" name="input_garray" direction="in" />??//这个Garray用来从client传递数据,包括复杂的数据结构到server
?? <arg type="i" name="outut_int" direction="out" />????//这个可以用,也可以不用
?? <arg type="ay" name="output_garray" direction="out" />?//这个Garray用来从server侧传回数据到client侧
????? <arg type="i" name="result" direction="out" />
??? </method>
? </interface>
</node>

大家知道:在dbus文档中有这么的描述,

ay | Array of bytes | DBUS_TYPE_G_BYTE_ARRAY | GArray *? |g_array_free??

大家都不常用字节数组(GArray),大家常用的是integar,string等;
这个通用的模板关键之处就是这个Garray, Garray本身是个容器,这个
容器里面可以装任何东西。

我们就是利用这个GArray来实现client与server之间数据的传递,无论想传递
什么要的数据;


第二步:用dbus的工具函数生成stub/proxy头文件,这一步写到Makefile脚本中,以后不用修改了;

dbus-binding-tool --mode=glib-server --prefix=your_module_name dbus_general.xml > general_stub.h
dbus-binding-tool --mode=glib-client --prefix=your_module_name dbus_general.xml > general_proxy.h

生成的头文件,大家一般不要动它们,直接使用就可以了;

general_proxy.h:

.....
client_request (DBusGProxy *proxy, const gint IN_action_id, const gint IN_input_int, const GArray* IN_input_garray, gint* OUT_output_int, GArray** OUT_output_garray, gint* OUT_result, GError **error)

{
? return dbus_g_proxy_call (proxy, "request", error, G_TYPE_INT, IN_action_id, G_TYPE_INT, IN_input_int, dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), IN_input_garray, G_TYPE_INVALID, G_TYPE_INT, OUT_output_int, dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), OUT_output_garray, G_TYPE_INT, OUT_result, G_TYPE_INVALID);
}
.....

general_stub.h:
.....

#include <dbus/dbus-glib.h>
static const DBusGMethodInfo dbus_glib_your_module_name_methods[] = {
? { (GCallback) __client_request_cb, dbus_glib_marshal_your_module_name_BOOLEAN__INT_INT_BOXED_POINTER_POINTER_POINTER_POINTER, 0 },
};

const DBusGObjectInfo dbus_glib_your_module_name_object_info = {
? 0,
? dbus_glib_your_module_name_methods,
? 1,
"org.freedesktop.DBus.general_api\0client_request\0S\0action_id\0I\0i\0input_int\0I\0i\0input_garray\0I\0ay\0output_int\0O\0F\0N\0i\0output_garray\0O\0F\0N\0ay\0result\0O\0F\0N\0i\0\0\0",
"\0",
"\0"
};
......

第三步:实现client侧,主要是直接调用general_proxy.h的接口函数client_request(),用GArray传入你的数组(可以携带任何你自己定义的数据结构)

gboolean proxy_func1 (void)
{
?int?api_id = 0; ?????//这个在不同的proxy_func里面可以有不同的值,主要是区分函数作用
?GArray*?in_array = NULL;
?GArray*?out_array = NULL;?//在这里不用分配内存,放在server侧做内存分配
?
?in_array = g_array_new(FALSE, FALSE, sizeof(guint8));
?if (!in_array)
??return FALSE;
??
?//把你自己的数据封装到in_array中,假设你的数据结构是your_strcut_t
?
?your_struct_t my_own_data;
?
?//fill my_own_data
?...
?
?//放到in_array中,这很关键
?g_array_append_vals(in_array, my_own_data, sizeof(your_strcut_t));??
?
?//调用general_proxy.h中的d