DBus研究笔记(二)

DBus研究笔记(二)一.关于DBusBinding   DBusbinding是对DBuslower-api的再一次封装,提供了更加便利的接口,有些binding还集成了事件循环,使用起来更加简洁。这里主要讨论的是Glibbinding的一些实现。二.一些基本概念1.代理(proxy)     一个代理就是一个远程其他应用里的某个进程下的对象在本地进程的表示,在之前我们看到的底

DBus研究笔记(二)"一.关于DBus Binding

      DBus binding是对DBus lower-api 的再一次封装,提供了更加便利的接口,有些binding还集成了事件循环,使用起来更加简洁。这里主要讨论的是Glib binding的一些实现。

二.一些基本概念

1.代理(proxy)

         一个代理就是一个远程其他应用里的某个进程下的对象在本地进程的表示,在之前我们看到的底层API消息传递过程中我们是自己手动创建一个消息然后再发送,接着等待应答。而如果使用代理,代理使用起来就像是一个本地对象,不过当你触发一个方法调用,它会转化为一个消息并发送给其他应用进程并等待应答,并取得返回值。

2.GObject

         GObject是一个用C语言编写的面向对象的函数库,它支持多个语言互通。它是GNOME的基础,在GTK+等应用上被广泛应用。GTK+2.0之前GObject是其一部分,后面开发者把大部分与GUI不相关的部分都移到了GObject,具体可以到http://zh.wikipedia.org/wiki/GObject这里了解。

三.利用XML描述DBus接口

        因为我们的主要目的是在GObject对象之间利用DBus进行通信。我们介绍一个最简单的方式来实现它。 dbus-bindings-tool,这个工具利用XML文件作为输入可以方便的生成服务器与客户端代码。

XML接口描述文件:

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE node PUBLIC
  	"-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
  "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">

<node>
  <interface name="org.maemo.Value">

	<method name="getvalue1">

	  <arg type="i" name="cur_value" direction="out"/>
	</method>

	<method name="getvalue2">
	  <arg type="d" name="cur_value" direction="out"/>
	</method>

	<method name="setvalue1">
	  <arg type="i" name="new_value" direction="in"/>
	</method>

	<method name="setvalue2">
	  <arg type="d" name="new_value" direction="in"/>
	</method>

  </interface>
</node>

说明:这里我们在接口org.maemo.Value下实现了四个接口,分别获取和设置变量值。每个Method以method为关键字一/method结尾,interface和node类似,node可以理解为一个对象。arg说明的是参数,type表示参数类型,name表示名称,direction表示方向。out说明是返回值。你可以添加任意多个interface以及method等,需要注意的是dbus-binding-tool工具会自动帮我们添加introspection接口(系统默认)。另为我们还需有文件类型定义DTD以便于校验工具可以方便的识别文件。

Makefile文件:

interface_xml := value-dbus-interface.xml

checkxml: $(interface_xml)
	@(xmllint) --valid --noout $(interface_xml)
	@(echo) $< check out ok

说明:这里需要用到一个叫xmllint的XML文件校验工具可以方便的校验我们在编写XML的过程中是否存在语法

lc@lc-Lenovo:~/DBus研究笔记$ make checkxml
value-dbus-interface.xml check out ok

四.生成中间胶和代码(glub code)

      我们利用Glib来绑定DBus之间必须有映射代码,我们利用dbus-binding-tool工具来生成。Makefile文件如下:

files := client-glub.h\
	 server-glub.h


client-glub.h:$(interface_xml)
			dbus-binding-tool --prefix=value_object --mode=glib-client  $< > $@


server-glub.h:$(interface_xml)
			dbus-binding-tool --prefix=value_object --mode=glib-server  $< > $@

说明:–prefix指定生成的glub code的前缀,–mode指定是客户端还是服务器。

lc@lc-Lenovo:~/DBus研究笔记$ make value-server-stub.h value-client-stub.h 
dbus-binding-tool --prefix=value_object --mode=glib-server \
	value-dbus-interface.xml > value-server-stub.h
dbus-binding-tool --prefix=value_object --mode=glib-client \
	value-dbus-interface.xml > value-client-stub.h
lc@lc-Lenovo:~/DBus研究笔记$ ls
DBus研究笔记(二)  Makefile             value-dbus-interface.xml
DBus研究笔记(一)  value-client-stub.h  value-server-stub.h

        生成的胶和代码后面我们在首发信号的时候可以方便的使用到,这里主要说几个问题:marshal(列集)函数是把数据转化为流的格式Unmarshaling(散集)是反操作,在绑定文件中,dbus-binding-tool自动生成函数将方法参数从dbus消息中还原出来,即实现了散集。glib有一些标准的列集函数,在gmarshal.h中定义。如果gmarshal.h没有提供适合的列集函数,我们可以用一个叫glib-genmarshal的工具自动生成列集函数。

五.创建GObject对象

          每个GOBJECT对象都有一个实例类和对象类,对象类里面的成员所有实例共有,而实例类成员属于单个成员。

typedef struct {
  /* The parent class object state. */
  GObject parent;
  /* Our first per-object state variable. */
  gint value1;
  /* Our second per-object state variable. */
  gdouble value2;
} ValueObject;

/* Per class state.
typedef struct {
  /* The parent class state. */
  GObjectClass parent;
} ValueObjectClass;

说明:我们这边在实例类里面定义了两个数据成员,接下来我们要编写method操作两个变量。

GType value_object_get_type(void);

/* 定义一些GOBJECT 对象常用的宏 */
#define VALUE_TYPE_OBJECT (value_object_get_type())

#define VALUE_OBJECT(object) \
        (G_TYPE_CHECK_INSTANCE_CAST((object), \
         VALUE_TYPE_OBJECT, ValueObject))
#define VALUE_OBJECT_CLASS(klass) \
        (G_TYPE_CHECK_CLASS_CAST((klass), \
         VALUE_TYPE_OBJECT, ValueObjectClass))
#define VALUE_IS_OBJECT(object) \
        (G_TYPE_CHECK_INSTANCE_TYPE((object), \
         VALUE_TYPE_OBJECT))
#define VALUE_IS_OBJECT_CLASS(klass) \
        (G_TYPE_CHECK_CLASS_TYPE((klass), \
         VALUE_TYPE_OBJECT))
#define VALUE_OBJECT_GET_CLASS(obj) \
        (G_TYPE_INSTANCE_GET_CLASS((obj), \
         VALUE_TYPE_OBJECT, ValueObjectClass))

/* Utility macro to define the value_object GType structure. */
G_DEFINE_TYPE(ValueObject, value_object, G_TYPE_OBJECT)

method声明:

gboolean value_object_getvalue1(ValueObject* obj, gint* value_out,
                                                  GError** error);
gboolean value_object_getvalue2(ValueObject* obj, gdouble* value_out,
                                                  GError** error);
gboolean value_object_setvalue1(ValueObject* obj, gint value_in,
                                                  GError** error);
gboolean value_object_setvalue2(ValueObject* obj, gdouble value_in,
                                                  GError** error);

实例类初始化:

static void value_object_init(ValueObject* obj) {
  dbg("Called");

  g_assert(obj != NULL);

  obj->value1 = 0;
  obj->value2 = 0.0;
}

对象类初始化:

static void value_object_class_init(ValueObjectClass* klass) {

  dbg("Called");

  g_assert(klass != NULL);

  dbg("Binding to GLib/D-Bus");

  /* 安装自定义对象. */
  dbus_g_object_type_install_info(VALUE_TYPE_OBJECT,
                                 &dbus_glib_value_object_object_info);

  dbg("Done");
}

DBUS路径接口定义:

/* Well-known name for this service. */
#define VALUE_SERVICE_NAME        "org.maemo.Platdev_ex"
/* Object path to the provided object. */
#define VALUE_SERVICE_OBJECT_PATH "/GlobalValue"
/* And we're interested in using it through this interface.
   This must match the entry in the interface definition XML. */
#define VALUE_SERVICE_INTERFACE   "org.maemo.Value"

主函数:

#include "common-defs.h"


int main(int argc, char** argv) {


  /* 初始化对象系统. */
  g_type_init();

  g_print(PROGNAME ":main Connecting to the Session D-Bus.\n");
  bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
  if (error != NULL) {
    handleError("Couldn't connect to session bus", error->message, TRUE);
  }
g_print(PROGNAME ":main Registering the well-known name (%s)\n",
          VALUE_SERVICE_NAME);

  /* 注册代理
     DBUS_SERVICE_DBUS = "org.freedesktop.DBus"
     DBUS_PATH_DBUS = "/org/freedesktop/DBus"
     DBUS_INTERFACE_DBUS = "org.freedesktop.DBus" */
  busProxy = dbus_g_proxy_new_for_name(bus,
                                       DBUS_SERVICE_DBUS,
                                       DBUS_PATH_DBUS,
                                       DBUS_INTERFACE_DBUS);
  if (busProxy == NULL) {
    handleError("Failed to get a proxy for D-Bus",
                "Unknown(dbus_g_proxy_new_for_name)", TRUE);
  }

  /* 申请名称. */
  if (!dbus_g_proxy_call(busProxy,
                        
                         "RequestName",
                         &error,
                         G_TYPE_STRING,
                         VALUE_SERVICE_NAME,
                         0,
                         G_TYPE_INVALID,
                         G_TYPE_UINT,
                         &result,
                         G_TYPE_INVALID)) {
    handleError("D-Bus.RequestName RPC failed", error->message,
                                                TRUE);
  }

  g_print(PROGNAME ":main RequestName returned %d.\n", result);
  if (result != 1) {
    handleError("Failed to get the primary well-known name.",
                  "RequestName result != 1", TRUE);}
valueObj = g_object_new(VALUE_TYPE_OBJECT, NULL);
  if (valueObj == NULL) {
    handleError("Failed to create one Value instance.",
                "Unknown(OOM?)", TRUE);
  }

  g_print(PROGNAME ":main Registering it on the D-Bus.\n");
  
  dbus_g_connection_register_g_object(bus,
                                      VALUE_SERVICE_OBJECT_PATH,
                                      G_OBJECT(valueObj));

  g_print(PROGNAME ":main Ready to serve requests (daemonizing).\n");

}

最后编译利用dbus-send发送消息调用Method进行测试。

今天的文章DBus研究笔记(二)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/30456.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注