Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3120309
  • 博文数量: 396
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4209
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-04 13:04
文章分类

全部博文(396)

文章存档

2022年(1)

2021年(2)

2020年(8)

2019年(24)

2018年(135)

2017年(158)

2016年(68)

我的朋友

分类: 嵌入式

2018-05-09 11:46:36


  在上次学习中,我们写了client小例子,非常简单,而且通过dbus-binding-tool生成的头文件,非常规范。相比执行,server稍微复杂些,仍然使用上次的xml文件,但是去掉annotation,更为本原一些。文件wei.xml如下:



 
   
     
     
   

 

  客户端小程序上次学习给出,正好用于实验。下面详细讲述步骤。

步骤一:生成头文件

dbus-binding-tool --mode=glib-server --prefix=com_wei wei.xml > wei_server.h

  注意,--prefix是不可缺少的参数,在有些文章中,没有提到这个,至少我在Moblin的操作系统中测试是需要的。通常来讲,对于项目,也需要提供一个区分的命名空间,无论是否必须,建议加上。"--prefix"参数定义了对象前缀。设对象前缀是$(prefix),则生成的DBusGObjectInfo结构变量名就是dbus_glib_$(prefix)_object_info。

生成了头文件wei_server.h如下:

/* Generated by dbus-binding-tool; do not edit! */


#ifndef __dbus_glib_marshal_com_wei_MARSHAL_H__
 
#define __dbus_glib_marshal_com_wei_MARSHAL_H__

#include   
 

G_BEGIN_DECLS
 

#ifdef G_ENABLE_DEBUG
 
#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
#define g_marshal_value_peek_char(v)     g_value_get_char (v)
#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
#define g_marshal_value_peek_int(v)      g_value_get_int (v)
#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
#define g_marshal_value_peek_long(v)     g_value_get_long (v)
#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
#define g_marshal_value_peek_float(v)    g_value_get_float (v)
#define g_marshal_value_peek_double(v)   g_value_get_double (v)
#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
#define g_marshal_value_peek_param(v)    g_value_get_param (v)
#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
#define g_marshal_value_peek_object(v)   g_value_get_object (v)
#else /* !G_ENABLE_DEBUG */
/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
 *          Do not access GValues directly in your code. Instead, use the
 *          g_value_get_*() functions
 */
#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
#endif /* !G_ENABLE_DEBUG */


/* BOOLEAN:UINT,POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.OI8HBV:1) */
 
extern void dbus_glib_marshal_com_wei_BOOLEAN__UINT_POINTER_POINTER (GClosure     *closure,
                                                                     GValue       *return_value,
                                                                     guint         n_param_values,
                                                                     const GValue *param_values,
                                                                     gpointer      invocation_hint,
                                                                     gpointer      marshal_data);
void
dbus_glib_marshal_com_wei_BOOLEAN__UINT_POINTER_POINTER (GClosure     *closure,
                                                         GValue       *return_value G_GNUC_UNUSED,
                                                         guint         n_param_values,
                                                         const GValue *param_values,
                                                         gpointer      invocation_hint G_GNUC_UNUSED,
                                                         gpointer      marshal_data)
{
  typedef gboolean (*GMarshalFunc_BOOLEAN__UINT_POINTER_POINTER) (gpointer     data1,
                                                                  guint        arg_1,
                                                                  gpointer     arg_2,
                                                                  gpointer     arg_3,
                                                                  gpointer     data2);
  register GMarshalFunc_BOOLEAN__UINT_POINTER_POINTER callback;
  register GCClosure *cc = (GCClosure*) closure;
  register gpointer data1, data2;
  gboolean v_return;

  g_return_if_fail (return_value != NULL);
  g_return_if_fail (n_param_values == 4);

  if (G_CCLOSURE_SWAP_DATA (closure))
    {
      data1 = closure->data;
      data2 = g_value_peek_pointer (param_values + 0);
    }
  else
    {
      data1 = g_value_peek_pointer (param_values + 0);
      data2 = closure->data;
    }
  callback = (GMarshalFunc_BOOLEAN__UINT_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);

  v_return = callback (data1,
                       g_marshal_value_peek_uint (param_values + 1),
                       g_marshal_value_peek_pointer (param_values + 2),
                       g_marshal_value_peek_pointer (param_values + 3),
                       data2);

  g_value_set_boolean (return_value, v_return);
}

G_END_DECLS
 

#endif /* __dbus_glib_marshal_com_wei_MARSHAL_H__ */
 

#include
static const DBusGMethodInfo dbus_glib_com_wei_methods[] = {
  { (GCallback) com_wei_test , dbus_glib_marshal_com_wei_BOOLEAN__UINT_POINTER_POINTER, 0 },
};

const DBusGObjectInfo dbus_glib_com_wei_object_info = {
  0,
  dbus_glib_com_wei_methods,
  1,
"com.wei.MyObject.Sample/0Test/0S/0x/0I/0u/0d_ret/0O/0F/0N/0d/0/0/0",
"/0",
"/0"
};

步骤二:编写Object文件

  在D-Bus学习(五) 和学习(六)中 ,我们给出了底层的例子,直接进行通信操作,没有涉及到对象的概念,使用Glib的高层接口编写的例子,我们可以生成对象,在对象中定义接口中方法和信令的操作。说实在,我对非JAVA的对象都不太熟悉,GObject更是……,不过工具嘛,照着用就是了。既然我们在xml中给出对象的路径,我们可以将对象命名为ComWeiMyObject。头文件com_wei_myobject.h如下:

#ifndef COM_WEI_MYOBJECT_H
#define COM_WEI_MYOBJECT_H
 

typedef struct ComWeiMyObject ComWeiMyObject;
typedef struct ComWeiMyObjectClass ComWeiMyObjectClass;

struct ComWeiMyObject
{
  GObject parent;
};

struct ComWeiMyObjectClass
{
  GObjectClass parent;
};

#define COM_WEI_MYOBJECT_TYPE  (com_wei_myobject_get_type())

GType com_wei_myobject_get_type(void);
gboolean com_wei_test(ComWeiMyObject * obj , const guint  IN_x, gdouble * OUT_d_ret, GError ** error);

#endif

  在头文件,我们定义了一个方法处理函数com_wei_test,这个函数也就是wei_server.h中com_wei_test。它的第一个参数就是对象,后面是这个方法的参数,包括输入和输出。下面是com_wei_myobject.c文件:

#include "com_wei_myobject.h" 

G_DEFINE_TYPE(ComWeiMyObject,com_wei_myobject,G_TYPE_OBJECT) 

static void com_wei_myobject_init(ComWeiMyObject * object)
{//这个两个init函数大概是GObject的套路,在这个简单的小例子中,没有什么特别的初始化处理 
}
static void com_wei_myobject_class_init(ComWeiMyObjectClass * klass)
{
}

gboolean com_wei_test (ComWeiMyObject * obj, const guint IN_x, gdouble* OUT_d_ret, GError ** error)
//我们只做测试,简单检测输入参数,直接回复输出结果 
  printf("com_wei_test() get input param: x= %d/n",IN_x);
  * OUT_d_ret = 0.99;
  return TRUE;
}

  实验例子尽量简单,在这个ComWeiMyObject的对象中实现了com.wei.MyObject.Sample接口的Test方法:com_wei_test。

步骤三:写Server程序

  OK,我们已经准备好写Server程序,由于Server需要长期监听,因此需要加入Loop循环。Loop已经在D-Bus学习四 的异步例子中学过。我们注意到使用GLib中函数与底层libdbus API的差异,例如底层API使用dbus_bus_get,高层GLib使用dbus_g_bus_get。这种命名方式,在我们提供更高层的接口时可以借鉴。GLib的D-Bus的API参考为

#include "com_wei_myobject.h"
#include "wei_server.h"  //注意此两头文件的先后顺序 

int main(int argc, char ** argv)
{
  DBusGConnection * conn;
  GMainLoop * main_loop = NULL;
  ComWeiMyObject * obj;
  GError * error = NULL;
  DBusGProxy * bus_proxy;
  int request_name_result;
 

  g_type_init();
  main_loop = g_main_loop_new(NULL,FALSE);
 
  //在自动生成的wei_server.h中定义了DBusGObjectInfo dbus_glib_com_wei_object_info, Install introspection information about the given object GType sufficient to allow methods on the object to be invoked by name. 这样,可以在收到信息的时候,可以触发调用它的方法。 
  dbus_g_object_type_install_info(COM_WEI_MYOBJECT_TYPE , & dbus_glib_com_wei_object_info ); 
  
  //建议与session dbus的连接,在以前学习过 
  conn = dbus_g_bus_get(DBUS_BUS_SESSION,&error);
  if(conn == NULL){
    g_printerr("Failed to connect D-Bus session Daemon!"); 
    g_error_free(error);
    return 1;
  } 

  
  //为连接起一个名字,对于GLib,这个处理比底层的API接口复杂,需要向系统DBus的管理者org.freedesktop.DBus,调用它的接口的方法"RequestName"来实现。居然更复杂,比较奇怪。 
  bus_proxy = dbus_g_proxy_new_for_name(conn, "org.freedesktop.DBus","/","org.freedesktop.DBus");
  if(!dbus_g_proxy_call(bus_proxy,"RequestName ",&error,
                    G_TYPE_STRING,"com.wei.test", G_TYPE_UINT,0, G_TYPE_INVALID,
                    G_TYPE_UINT, &request_name_result, G_TYPE_INVALID)){
    g_printerr("Request Name error : %s/n",error->message);
    return 1;
  }
  
  obj = g_object_new(COM_WEI_MYOBJECT_TYPE,NULL); 

  
//将对象在指定的path注册到连接上。 Registers a GObject at the given path. 当有消息通过连接,经过路径,找到对象后,根据前面前面的dbus_g_object_type_insall_info,能够调用对应的处理方式。 
  dbus_g_connection_register_g_object(conn, "/com/wei/MyObject",G_OBJECT(obj)); 

  g_main_loop_run(main_loop);
  return 0;
 
}

  OK,完成。如果我们像上一次学习在xml中对方法加上,则该方法的调用函数不是自动生成的com_wei_test,而是wei_response。通过这种方式,我们可以指定我们想使用的名字,这在tutorial 中详细介绍。

阅读(757) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~