Maemo Linux手机平台系列分析:8 Maemo平台开发之 使用Glib绑定的D-Bus

BlueZ-5.35蓝牙设备扫描源码分析 BlueZ-5.35中关于扫描相关的源码分析; 阅读详情

 

使用 Glib 封装过的 D-Bus
这部分的内容:
  • GObject介绍
  • 使用XML文件定义D-Bus接口
  • 自动生成proxy/stub代码
  • 创建一个简单的D-Bus对象
  • 通过D-Bus发布一个GType类型
  • 客户端如何使用Glib封装过的D-Bus
  • D-Bus的自省功能
 
GObject 介绍
为了在运行时把 GTK+ widgets 绑定到解释语言,一些牛人就用 C 语言实现了相对难以理解的面向对象的机制。根据你个人的爱好,你可以把这种面向对象称之为 GObject 或者 GType 。 GType 是 GObject 的底层基础。 GObject/GType 是 Glib 的一部分,并且单独编译成一个库: libgobject ,对于 GObject 的详细介绍,大家可以到网上 google 一下,另外还要仔细阅读其代码,非常巧妙的实现!
这里的例子:实现一个非继承的类,类的接口去访问和修改两个私有的成员变量: value1 和 vaule2, value1 是 32 位的整数, value2 是一个 gdouble 类型的数据。
我们需要实现类构造函数和对象构造函数。这里,这两个构造函数都比较简短。如果你了解 C++, 你会发现这里怎么有两个构造函数呢? C++ 只有一个啊!不错,这就是 GObject 别扭的地方。慢慢你就会习惯的,当你很喜欢它后,你可能觉得 C++ 是个另类。因为你了解 C++ 的构造函数比较早,这个晚了些时候。
 
使用 XML 文件定义 D-Bus 接口:
 
由于我们主要的目的是做一个可以在 D-Bus 中使用的对象,因此我们从一个最简单的地方入手,通过 dbus-binding-tool 工具,这个工具会自动由 XML 文件生成 client 和 server 端的代码。我们就是把需要的接口安装 XML 语法定义在一个 XML 文件中就行了。
定义 “ 方法 ” ,即函数:用 method 来包含,其 name 是指定这个函数的名字,这个指定的名字会拷贝到生成的 stub 代码里面;函数 method 带一个参数: new_value, 用 <arg /> 包含。其中对于参数类型 (type) 的的形式,需要参考 D-Bus 的参数类型定义。
    <!-- setvalue1(int newValue): sets value1 -->
    <method name="setvalue1">
      <arg type="i" name="new_value" direction="in"/>
    </method>
 
// direction 表示入口参数还是出口参数,in:入口; out: 出口参数,如果不指定in或者out, 默认为in;
// type 的指定要参考D-Bus的类型定义,见下表;
 
其中,最难搞的就是要严格指定参数 (arg) 的类型( type ),正是这个 type 来定义参数的数据类型, D-Bus 定义的参数类型如下:

Conventional Name
Code
Description
INVALID
0 (ASCII NUL)
Not a valid type code, used to terminate signatures
BYTE
121 (ASCII 'y')
8-bit unsigned integer
BOOLEAN
98 (ASCII 'b')
Boolean value, 0 is FALSE and 1 is TRUE . Everything else is invalid.
INT16
110 (ASCII 'n')
16-bit signed integer
UINT16
113 (ASCII 'q')
16-bit unsigned integer
INT32
105 (ASCII 'i')
32-bit signed integer
UINT32
117 (ASCII 'u')
32-bit unsigned integer
INT64
120 (ASCII 'x')
64-bit signed integer
UINT64
116 (ASCII 't')
64-bit unsigned integer
DOUBLE
100 (ASCII 'd')
IEEE 754 double
STRING
115 (ASCII 's')
UTF-8 string (must be valid UTF-8). Must be nul terminated and contain no other nul bytes.
OBJECT_PATH
111 (ASCII 'o')
Name of an object instance
SIGNATURE
103 (ASCII 'g')
A type signature
ARRAY
97 (ASCII 'a')
Array
STRUCT
114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')
Struct
VARIANT
118 (ASCII 'v')
Variant type (the type of the value is part of the value itself)
DICT_ENTRY
101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}')
Entry in a dict or map (array of key-value pairs)

 
我用蓝色标出的是比较常用的,你要根据你参数的需要,把上述第二列的类型码写到 XML 文件中去。开始你可能不习惯,慢慢就好了。
另外, D-Bus 本身并不限制返回参数的个数,但是 C 语言只支持一个返回参数,因此如果你需要把其它需要携带回来的参数当作出口参数处理。其它的一些高级语言并不像 C 语言这样有限制。
 
下面是 D-Bus 函数所能支持的参数类型: ( 括号中是 Glib 对应的类型 ):
  • b: boolean (gboolean)
  • y: 8-bit unsigned integer (guint8)
  • q/n: 16-bit unsigned/signed integer (guint16/gint16)
  • u/i: 32-bit unsigned/signed integer (guint32/gint32)
  • t/x: 64-bit unsigned/signed integer (guint64/gint64)
  • d: IEEE 754 double precision floating point number (gdouble)
  • s: UTF-8 encoded text string with NUL termination (only one NUL allowed) (gchar* with additional restrictions)
  • a: Array of the following type specification (case-dependent)
  • o/g/r/(/)/v/e/{/}: Complex types, please see the official D-Bus documentation on type signatures.
从这个列表可以看出,我们上面定义的函数: setvalue1 有一个 32 位整形参数 (new_value). 这里定义的参数名称: new_value 将会影响到所生成的 stub 代码,对于生成文档和 D-Bus 自省是非常有用的。
下面我们再定义另外一个函数: getvalue1 , 这个函数用于返回当前对象的整数成员的值,没有入口参数,只有出口参数 : cur_value 。具体定义见下:
    <!-- getvalue1(): returns the first value (int) -->
    <method name="getvalue1">
      <arg type="i" name="cur_value" direction="out"/>
    </method>
我们已经知道, D-Bus 的 method 是隶属于 interface 的,就说一个 interface 可以有 N 个 method, 在 XML 中,我们把这些 method 元素包含在 interface 元素中,借以表达这种隶属关系。这个 interface 的名字属性是可选的,你可以指定,也可以不指定,我们强烈推荐你写上这个名字,一是防止各个模块的 interface 重名,另外一个重要的功用是为了 introspection.
再进一步, method 隶属于 interface, 那么 interface 又属于谁呢?隶属于 object, 一个 object 可以有 N 个 interface. 我们把 interface 元素包含在 node 元素内。在 XML 中, node 是最顶层的元素了。我们这个例子里面,只实现了一个 interface(binding tool 会自动增加 introspection 接口的,因此不必在 XML 文件中指定 ) ,到此,我们就写完了一个最基本的 XML 文件,如下:
<?xml version="1.0" encoding="UTF-8" ?>
<node>
 <interface name="org.maemo.Value">
    <!-- getvalue1(): returns the first value (int) -->
    <method name="getvalue1">
      <arg type="i" name="cur_value" direction="out"/>
    </method>
    <!-- setvalue1(int newValue): sets value1 -->
    <method name="setvalue1">
      <arg type="i" name="new_value" direction="in"/>
    </method>
 </interface>
</node>
 
再对上面的最基本的 XML 接口定义文件做些扩充:增加 DTD 扫描,其实这个可以不用。另外还有就是增加了 2 个函数定义: get_value2, set_value2 。
如果你需要写 XML 文件,强烈建议你在一个模板基础上写,就是拿个没有基本语法错误的模板,然后增加修改你的接口,这样容易成功,不要白手起家,不要在这个 XML 文件上面做过多的纠缠。
<?xml version="1.0" encoding="UTF-8" ?>
 
<!-- This maemo code example is licensed under a MIT-style license,
     that can be found in the file called "License" in the same
     directory as this file.
     Copyright (c) 2007 Nokia Corporation. All rights reserved. -->
 
<!-- If you keep the following DOCTYPE tag in your interface
     specification, xmllint can fetch the DTD over the Internet
     for validation automatically. // 自动对你定义的接口、方法、参数进行扫描,检查其合法性,如果你没有联网,就不要加这个了 -->
<!DOCTYPE node PUBLIC
 "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
 "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
 
<!-- This file defines the D-Bus interface for a simple object, that
     will hold a simple state consisting of two values (one a 32-bit
     integer, the other a double).
 
     The interface name is "org.maemo.Value".
     One known reference implementation is provided for it by the
     "/GlobalValue" object found via a well-known name of
     "org.maemo.Platdev_ex". -->
 
<node>
 <interface name="org.maemo.Value">
 
    <!-- Method definitions -->
 
    <!-- getvalue1(): returns the first value (int) -->
    <method name="getvalue1">
      <!-- NOTE Naming arguments is not mandatory, but is recommended
                so that D-Bus introspection tools are more useful.
                Otherwise the arguments will be automatically named
                "arg0", "arg1" and so on. -->
      <arg type="i" name="cur_value" direction="out"/>
    </method>
 
    <!-- getvalue2(): returns the second value (double) -->
    <method name="getvalue2">
      <arg type="d" name="cur_value" direction="out"/>
    </method>
 
    <!-- setvalue1(int newValue): sets value1 -->
    <method name="setvalue1">
      <arg type="i" name="new_value" direction="in"/>
    </method>
 
    <!-- setvalue2(double newValue): sets value2 -->
    <method name="setvalue2">
      <arg type="d" name="new_value" direction="in"/>
    </method>
 
 </interface>
</node>
 
写完 XML 文件后,下面我们是不是可以使用 D-Bus 工具来生成代码了?别急!我们还要对 XML 文件做些自动检查。主要检查两个方面:是否符合 XML1.0 规范;验证 XML 结构(即:元素是否成对匹配)。结构验证的规则是由 DTD(Document Type Definition) 文档规定的。 D-Bus 规定的 XML 格式如下:

<!-- DTD for D-BUS Introspection data -->
<!-- (C) 2005-02-02 David A. Wheeler; released under the D-BUS licenses,
         GNU GPL version 2 (or greater) and AFL 1.1 (or greater) -->
 
<!-- see D-BUS specification for documentation -->
 
<!ELEMENT node (interface*,node*)>
<!ATTLIST node name CDATA #REQUIRED>
 
<!ELEMENT interface (annotation*,method*,signal*,property*)>
<!ATTLIST interface name CDATA #REQUIRED>
 
<!ELEMENT method (annotation*,arg*)>
<!ATTLIST method name CDATA #REQUIRED>
 
<!ELEMENT arg EMPTY>
<!ATTLIST arg name CDATA #IMPLIED>
<!ATTLIST arg type CDATA #REQUIRED>
<!-- Method arguments SHOULD include "direction",
     while signal and error arguments SHOULD not (since there's no point).
     The DTD format can't express that subtlety. -->
<!ATTLIST arg direction (in|out) "in">
 
<!ELEMENT signal (arg,annotation)>
<!ATTLIST signal name CDATA #REQUIRED>
 
<!ELEMENT property (annotation)> <!-- AKA "attribute" -->
<!ATTLIST property name CDATA #REQUIRED>
<!ATTLIST property type CDATA #REQUIRED>
<!ATTLIST property access (read|write|readwrite) #REQUIRED>
 
<!ELEMENT annotation EMPTY> <!-- Generic metadata -->
<!ATTLIST annotation name CDATA #REQUIRED>
<!ATTLIST annotation value CDATA #REQUIRED>
 

然后根据这个模板对你定义的 XML 文档进行规则检查。
仅仅检查了 DTD 有效性,还不完美:因为 DTD 类型检查只是对语法做检查,并不能对语义 / 含义做检查。
为了检查语义,我们使用另外一个工具: checkxml, 把它写到你的 makefile 中:
# One extra target (which requires xmllint, from package libxml2-utils)
# is available to verify the well-formedness and the structure of the
# interface definition xml file.
#
# Use the 'checkxml' target to run the interface XML through xmllint
# verification. You'll need to be connected to the Internet in order
# for xmllint to retrieve the DTD from fd.o (unless you setup local
# catalogs, which are not covered here).
 
# ... Listing cut for brevity ...
 
# Interface XML name (used in multiple targets)
interface_xml := value-dbus-interface.xml
 
# ... Listing cut for brevity ...
 
# Special target to run DTD validation on the interface XML. Not run
# automatically (since xmllint isn't always available and also needs
# Internet connectivity).
checkxml: $(interface_xml)
      @xmllint --valid --noout $<
      @echo $< checks out ok
检查语义:
 
[sbox-CHINOOK_X86: ~/glib-dbus-sync] > make checkxml
value-dbus-interface.xml checks out ok
 
为了验证 DTD/checkxml 能否起到作用,我们简单修改一下上面的 XML 文件,增加一个 DTD 中没有规定的节点 </invalidElement> , 并且去掉一个 method 开始标签,看看效果:
[sbox-CHINOOK_X86: ~/glib-dbus-sync] > make checkxml
value-dbus-interface.xml:36: element invalidElement: validity error :
 No declaration for element invalidElement
    </invalidElement>
              ^
value-dbus-interface.xml:53: parser error :
 Opening and ending tag mismatch: method line 39 and interface
 </interface>
              ^
value-dbus-interface.xml:54: parser error :
 Opening and ending tag mismatch: interface line 22 and node
</node>
       ^
value-dbus-interface.xml:55: parser error :
 Premature end of data in tag node line 21
 
^
make: *** [checkxml] Error 1
上面,第一个被发现的错误 ( 验证错误 ) ,是由于 XML 文件不符合 DTD 的规定导致的。第二个 ( 解析错误 ) 则是没有正确的书写 XML 。
完成 XML 文件的两方面的检查后,我们开始生成代码。这个生成的代码我们叫它“ glue” 代码,什么意思呢? glue 的本意是粘合,就是通过 glue 代码完成从 Glib 到 D-Bus 的映射关系:
图:
由 XML 文件,运行 dbus-binding-tool 命令,辅以不同的参数,可以生成 client 侧和 sever 侧的 stub 代码,生成的 client stub 和 server stub 代码正好构成了 Client/Server 结构。由这两个 stub 来完成 Glib 与 D-Bus 的互通,由于应用程序使用 Glib ,进而完成应用程序与 D-Bus 的互通。我们把 makefile 改写一下:
# Define a list of generated files so that they can be cleaned as well
cleanfiles := value-client-stub.h /
              value-server-stub.h
 
# ... Listing cut for brevity ...
 
# If the interface XML changes, the respective stub interfaces will be
# automatically regenerated. Normally this would also mean that your
# builds would fail after this since you'd be missing implementation
# code.
# 这里的—prefix前缀会反映到你的stub代码中,会在生成的结构变量和函数名称中添加这个前缀,这个前缀大家不要省略,因为这里仅仅是生成头文件,实际的实现代码需要我们自己写,但是我们需要拷贝这里的声明到.c文件中,如果不指定这个前缀,并且有多个模块的话,会冲突的;
 
# mode 指定为glib-server就生成server stub代码;指定为glib-client
# 则生成client stub代码
 
# 生成sever stub代码
value-server-stub.h: $(interface_xml)
      dbus-binding-tool --prefix=value_object --mode=glib-server /
       $< > $@
 
# 生成client stub代码
value-client-stub.h: $(interface_xml)
      dbus-binding-tool --prefix=value_object --mode=glib-client /
       $< > $@
 
# ... Listing cut for brevity ...
 
clean:
      $(RM) $(targets) $(cleanfiles) *.o
这里生成的 client 侧的代码是想通过 Glib 去访问对象的实现,而 server 侧代码则是实现对象。
生成两个头文件 :
[sbox-CHINOOK_X86: ~/glib-dbus-sync] > 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
[sbox-CHINOOK_X86: ~/glib-dbus-sync] > ls -la value*stub.h
-rw-rw-r-- 1 user user 5184 Nov 21 14:02 value-client-stub.h
-rw-rw-r-- 1 user user 10603 Nov 21 14:02 value-server-stub.h
在开始实现实际的对象之前,我们先来瞄一眼生成的代码,看看到底什么妖蛾子。先看看 server 侧的 stub 文件:
/* Generated by dbus-binding-tool; do not edit! */
 
 /*... Listing cut for brevity ...*/
 
#include <dbus/dbus-glib.h>
static const DBusGMethodInfo dbus_glib_value_object_methods[] = {
 { (GCallback) value_object_getvalue1,
    dbus_glib_marshal_value_object_BOOLEAN__POINTER_POINTER, 0 },
 { (GCallback) value_object_getvalue2,
    dbus_glib_marshal_value_object_BOOLEAN__POINTER_POINTER, 47 },
 { (GCallback) value_object_setvalue1,
    dbus_glib_marshal_value_object_BOOLEAN__INT_POINTER, 94 },
 { (GCallback) value_object_setvalue2,
    dbus_glib_marshal_value_object_BOOLEAN__DOUBLE_POINTER, 137 },
} ;
 
const DBusGObjectInfo dbus_glib_value_object_object_info = {
 0,
 dbus_glib_value_object_methods,
  4,
"org.maemo.Value /0 getvalue1 /0 S /0 cur_value /0 O /0F/0 N /0 i /0/0 "
"org.maemo.Value /0 getvalue2 /0 S /0 cur_value /0 O /0F/0 N /0 d /0/0 "
"org.maemo.Value /0 setvalue1 /0 S /0 new_value /0 I /0 i /0/0 "
"org.maemo.Value /0 setvalue2 /0 S /0 new_value /0 I /0 d /0/0/0 " ,
" /0 " ,
" /0 "
} ;
[ The method table and object introspection data (glib-dbus-sync/value-server-stub.h) ]
在这个头文件中,生成的 4 个函数: value_object_getvalue1 , value_object_getvalue2 , value_object_setvalue1 value_object_setvalue2 . 需要我们去实现;在函数表 dbus_glib_value_object_methods ,由函数地址; marshalling 函数(用于在 Glib 和 D-Bus 之间 marshal 数据)组成。
Marshaling 的作用就是参数从一种形式转换为另外一种形式,主要是为了两种不同参数能互相兼容地传递。 Marshalling 技术是在大多数 RPC 中运用的。由于 Glib 和 D-Bus 各自有不同的类型系统,如果我们手动去写这种转换代码,是很乏味和无聊的。 Binding tool 可以帮忙解决这个问题。
上述头文件中还有一个比较有意思的东西: xxx_object_info 结构变量,这个结构变量是要注册给 D-Bus daemon 的,并且把它发布在通道 (bus) 中 ( 然后 client 侧才能发现并调用其函数 ) ,这个过程其实和我们的生活很贴近,比如公交车上的电视广告:厂家把商品 ( 看作 object) 的广告,送到广告发布商那里,广告商把该广告投放到公交车 ( 看作 D-Bus daemon) 的电视中 , 消费者 ( 看作 client) 看到了该广告,可能购买这个产品 ( 调用 object 的函数 ) 。 上面很长的字符串将会安装 interface 规范的样式进行压缩编码,对于函数名、参数等也是按照这样编码的。在这个头文件中还有很多自省的代码,这也是非常重要的部分,最后再解释。
正如头文件的第一句提示:这是 dbus-binding-tool 自动生成的代码,请不要编辑它。因为每次编译都回自动生成这个文件,你如果修改了这里的头文件,会被覆盖掉的。所以最好不要修改。那如何使用这里的代码呢,你只要拷贝粘帖这里的代码到 .c 文件中就行了。
下面我们就继续:实现在 server stub 函数表中调用的具体函数。 We'll next continue with the server implementation for the functions that are called via the method table.
 
定义一个对象,这个过程就是 GObject 的八股文:
/* This defines the per-instance state.
 
   Each GObject must start with the 'parent' definition so that common
   operations that all GObjects support can be called on it. */
typedef struct {
 /* The parent class object state. */
 GObject parent; // 要继承自GObject,这样才能用GObject的便利
 /* Our first per-object state variable. */
 gint value1;
 /* Our second per-object state variable. */
 gdouble value2;
} ValueObject;
 
/* Per class state.
 
   For the first Value implementation we only have the bare minimum,
   that is, the common implementation for any GObject class. */
typedef struct {
 /* The parent class state. */
 GObjectClass parent;
} ValueObjectClass;
下面接着定义一些宏,全是用 G_TYPE_ 开头的,你不必知道的太多,会套用就行,如果想知道的很详细,可以参考: http://maemo.org/api_refs/4.0/gobject/index.html.
/* Forward declaration of the function that will return the GType of
   the Value implementation. Not used in this program since we only
   need to push this over the D-Bus. */
GType value_object_get_type(void);
 
/* Macro for the above. It is common to define macros using the
   naming convention (seen below) for all GType implementations,
   and that's why we're going to do that here as well. */
 
/* 下面这些定义其实就是“八股文”,固定的格式,你只要套用就行,等熟悉了后,你也不会一个个写,而是拷贝模板。
*/
#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)
宏定义完成后,下面我们就着手实现实例初始化和类初始化,类的初始化中我们调用了 D-Bus 的接口函数,把我们的对象信息注册给了 D-Bus 了,就是暴露在通道( bus )中了,这样,客户端就能找到这个对象了。
/**
 * Since the stub generator will reference the functions from a call
 * table, the functions must be declared before the stub is included.
 */
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);
 
/**
 * Pull in the stub for the server side.
 */
#include "value-server-stub.h"
 
 /*... Listing cut for brevity ...*/
 
/**
 * Per object initializer
 *
 * Only sets up internal state (both values set to zero)
 */
static void value_object_init(ValueObject* obj) {
 dbg("Called");
 
 g_assert(obj != NULL);
 
 obj->value1 = 0;
 obj->value2 = 0.0;
}
 
/**
 * Per class initializer
 *
 * Registers the type into the GLib/D-Bus wrapper so that it may add
 * its own magic.
 */
static void value_object_class_init(ValueObjectClass* klass) {
 
 dbg("Called");
 
 g_assert(klass != NULL);
 
 dbg("Binding to GLib/D-Bus");
 
 /* Time to bind this GType into the GLib/D-Bus wrappers.
     NOTE: This is not yet "publishing" the object on the D-Bus, but
           since it is only allowed to do this once per class
           creation, the safest place to put it is in the class
           initializer.
           Specifically, this function adds "method introspection
           data" to the class so that methods can be called over
           the D-Bus. */
 dbus_g_object_type_install_info(VALUE_TYPE_OBJECT,
                                 &dbus_glib_value_object_object_info);
 
 dbg("Done");
 /* All done. Class is ready to be used for instantiating objects */
}
 
下面我们实现具体的 get /set 函数,也就是 object 提供的 methods 。请注意:函数名和参数都要和 stub 头文件中的一模一样 :
/**
 * Function that gets called when someone tries to execute "setvalue1"
 * over the D-Bus. (Actually the marshaling code from the stubs gets
 * executed first, but they will eventually execute this function.)
 *
 * NOTE: If you change the name of this function, the generated
 *       stubs will no longer find it! On the other hand, if you
 *       decide to modify the interface XML, this is one of the places
 *       that you'll have to modify as well.
 *       This applies to the next four functions (including this one).
 */
gboolean value_object_setvalue1(ValueObject* obj, gint valueIn,
                                                  GError** error) {
 
 dbg("Called (valueIn=%d)", valueIn);
 
 g_assert(obj != NULL);
 
 /* Change the value. */
 obj->value1 = valueIn;
 
 /* Return success to GLib/D-Bus wrappers. In this case we don't need
     to touch the supplied error pointer-pointer. */
 return TRUE;
}
 
/**
 * Function that gets executed on "setvalue2".
 * Other than this function operating with different type input
 * parameter (and different internal value), all the comments from
 * set_value1 apply here as well.
 */
gboolean value_object_setvalue2(ValueObject* obj, gdouble valueIn,
                                                  GError** error) {
 
 dbg("Called (valueIn=%.3f)", valueIn);
 
 g_assert(obj != NULL);
 
 obj->value2 = valueIn;
 
 return TRUE;
}
 
/**
 * Function that gets executed on "getvalue1".
 */
gboolean value_object_getvalue1(ValueObject* obj, gint* valueOut,
                                                  GError** error) {
 
 dbg("Called (internal value1 is %d)", obj->value1);
 
 g_assert(obj != NULL);
 
 /* Check that the target pointer is not NULL.
     Even is the only caller for this will be the GLib-wrapper code,
     we cannot trust the stub generated code and should handle the
     situation. We will terminate with an error in this case.
 
     Another option would be to create a new GError, and store
     the error condition there. */
 g_assert(valueOut != NULL);
 
 /* Copy the current first value to caller specified memory. */
 *valueOut = obj->value1;
 
 /* Return success. */
 return TRUE;
}
 
/**
 * Function that gets executed on "getvalue2".
 * (Again, similar to "getvalue1").
 */
gboolean value_object_getvalue2(ValueObject* obj, gdouble* valueOut,
                                                  GError** error) {
 
 dbg("Called (internal value2 is %.3f)", obj->value2);
 
 g_assert(obj != NULL);
 g_assert(valueOut != NULL);
 
  *valueOut = obj->value2;
 return TRUE;
}
 
如何通过dbus开发bluez(c语言版) 如何通过c语言去开发bluez,截至到我写这篇文章为止,百度,谷歌搜下来,估计就csdn一个写套例子放在csdn上,但我没会员,也就没下来看了。这里我提供个简单的蓝牙扫描例子,以此来敲砖引玉。看一下应该很容易就明白了。bluez要如何通过dbus操作,通过上面的说明应该已经很清晰,另外的一些blues使用逻辑可以参考bluetoothctl源码和test/里面的python代码。 阅读详情

相关推荐

Maemo Linux手机平台系列分析:6 Maemo平台开发之D-Bus

    在Maemo平台中,D-Bus是一个非常重要的中间件(middleware)解决方案,主要用于进程之间的通信。已经有很多服务使用了D-Bus,接下来将介绍不同的方法去实现。D-Bus是贯穿于Maemo平台的,离不开D-Bus。  这部分的内容: 介绍一下D-Bus D-Bus的架构 D-Bus的地址和名字 在Maemo中D-Bus的作用

Linux智能手机--cuijpus的专栏 6057

GDBus之属性使用

本篇涉及的知识: 1.dbus Property的set与get操作、参数传递 2.dbus PropertiesChanged信号如何捕获 property-test.c 文件 #include <glib.h> #include <gio/gio.h> #include <stdio.h> const char beijing_dbus_server_name[] = {"world.china.beijing.test"}; //dbus服务名 const c

qq_943588990的博客 2036

dbus测试程序

dbus 测试 glib

【Linux】【蓝牙】如何基于Linux实现Beacon与Beacon Scan

一、背景 最近在思考如何用最精简的方式实现beacon与beacon scan 二、实现方式 1,mgmt实现逻辑 a: 扫描命令: { "find", "[-l|-b] [-L]", cmd_find, "Discover nearby devices" }, { "find-service", "[-u UUID] [-r RSSI_Threshold] [-l|-b]", cmd_find_service, "Discover nearby service" }, { "stop-find",

u014028690的博客 2099

5分钟搞定!用Keil MDK将STM32F103C8T6工程无缝迁移到ZET6开发板

本文详细介绍了如何在Keil MDK环境下快速将STM32F103C8T6工程迁移到ZET6开发板,涵盖硬件差异对比、工程配置调整、外设适配及编译排错等关键步骤,帮助开发者5分钟内完成工程移植,大幅提升开发效率。

weixin_30879169的博客 408

spark 适配达梦数据库

spark 适配达梦数据库 版本 spark3.0.0 scala2.12.10 DM Database Server 64 V8 步骤一: 引驱动包: SBT方式: "com.dameng" % "Dm8JdbcDriver18" % "8.1.0.157", maven方式: <dependency> <groupId>com.dameng</groupId> <artifactId>Dm8JdbcDriver18</artifac

_@Eva@_的博客 2090

maemo hildon-desktop(2)

maemo hildon-desktop(2)老版本的源码地址  http://repository.maemo.org/首先看一下 desktop 类型 struct _HDDesktopPrivate {  gchar                 *c

613

在中国大陆使用 LiveKit 集成阿里云语音交互服务

通过集成阿里云的语音和模型服务,我们可以快速构建出适合中国用户的 LiveKit 智能语音应用。LiveKit Agents 框架的模块化设计使得替换底层服务变得异常简单,只需要更换相应的插件实例即可。使用 WebSocket 版本的阿里云 ASR 接口以获得更低的延迟。利用通义千问的 Function Calling 能力对接智能家居或企业内部 API。结合 LiveKit 的视频处理能力,打造具备视觉交互的数字人。希望这篇博客能为你在实时音视频与 AI 结合的探索之路上提供帮助!

星空漫野 1236

Maemo Linux手机平台系列分析:9 Maemo平台开发之 使用D-Bus信号做异步操作

   使用D-Bus信号做异步操作 D-Bus信号的属性 在XML文件中声明信号 从GObject对象中发射信号 在客户端捕获信号 跟踪D-Bus信号 D-Bus信号的属性:      通过D-Bus实现远程函数调用(RPC)只是D-Bus的一半功能,另外D-Bus也支持广播通信,也称之为异步通信。这种异步通信机制在

Linux智能手机--cuijpus的专栏 1713

VMware Workstation 17 Pro 保姆级教程:手把手教你安装银河麒麟 Kylin V10 SP3 国产系统

本文提供VMware Workstation 17 Pro安装银河麒麟Kylin V10 SP3的详细教程,涵盖环境准备、虚拟机配置、系统安装及优化全流程。通过分步指导和实用技巧,帮助用户高效搭建国产操作系统开发测试环境,特别适合技术自主可控需求场景下的虚拟化实践。

weixin_30879169的博客 645

小红书爬取实战指南

以上方案仅供技术学习参考,请确保遵守目标网站的服务条款和相关法律法规。

monk all the way 6923

D-Bus学习(一):总体介绍

D-Bus的方式在移动手机操作系统中非常重要,包括Maemo,Moblin等以Linux为基础的操作系统。估计Andriod也大量使用。D-Bus的相关学习资料见:http://www.freedesktop.org/wiki/Software/dbus ,在网上也有大量的学习资料,在http://blog.chinaunix.net/u3/111961/ 中有不少的中文资料,收集了很多网络资料。

billxin2012的专栏 697

【人工智能的数学基础】最优传输(Optimal Transport)问题与Wasserstein距离

代表两堆石子,则问题等价于如何移动一堆石子,通过最小的累积移动距离把它堆成另外一堆石子。的不同位置分配的值。为离散型概率分布,则该优化问题可以表示为矩阵形式。表示寻找总运输成本最小的方案。放大后的上确界不会小于原来的上确界,因此不妨取。具有相同的概率分布。是概率分布,因此积分可以写作采样形式。描述了一种可行的运输方案,表示应该从位置。则最优传输问题的目标函数可以用列向量。对于一个线性规划问题,总可以写出其。的所有可能联合分布的集合,下确界。其中矩阵的每一行代表概率分布。表示寻找使得目标函数最大的。

AI天才研究院 6328

Development Environment of Maemo

You can find online document on:http://wiki.maemo.org/Documentation/Maemo_5_Final_SDK_Installation(1) At first you should install Xephyr :apt-get install xserver-xephyr(2) Installing Maemo 5 SDK:1

第三只眼的专栏 1011

由异常的测试眼图引发的深入思考

信号测试中出现“双眼皮”的眼图测试效果,可能的导致因素总结如下:PCB通道阻抗设计不匹配,负载端出现严重反射;发射端采用了不当的信号预处理;接收器均衡处理不当;通道串扰严重... 基于以上的假设,本文就逐一分析下这些因素到底是如何对正常的信号眼图造成影响的。

一只豌豆象的博客 3062

CloudCompare 二次开发(16)——计算点云最值

不依赖任何第三方点云相关库,使用ClopudCompare计算点云最值。

点云侠的博客 517

如何创建Maemo应用程序(转)

如何创建Maemo应用程序 From Forum Nokia Wiki 本文是一篇对Maemo.org开源社区官方文档How to Write New Applications in maemo 4.0的非正式简体中文翻译版本。希望本文对广大中国开发者了解Maemo平台以及开发Maemo平台应用程序带来一些帮助:) C...

weixin_34250434的博客 147

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Nokia Qt SDK开发环境使用

Nokia Qt SDK是诺基亚专门为跨平台手机开发Qt应用推出的开发工具,相比以往的SDK,它具有如下特点: 安装更简便:只需要下载一个安装包 模拟器启动更快: 利用Qt重新开发了轻量级的模拟器 真正跨平台:利用一个开发工具可以同时开发Symbian,maemo以及模拟器上的应用 支持硬件调试 开发平台可扩展:通过扩展,可以开发其它平台的应用,比如Windows,Mac等平台的应用 ...

weixin_34390996的博客 195

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

在Ubuntu 9.10上搭建Maemo 5及Qt 4开发环境

 Maemo是Linux的一个嵌入式发行版,支持ARM构架,其开发环境自然是桌面Linux了。由于Maemo使用了Debian包管理系统,所以最好还是在Debian或者Ubuntu上搭建开发环境了(目前支持X86和ARM两个构架)。为了简化开发,推荐使用Scratchbox作为沙盒,该软件能够很好的虚拟Maemo环境以便于调试,并提供了很好的跨平台编译支持。如果你没有Linux环境

Xizhi Zhu的博客 3291

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Maemo Linux手机平台系列分析:5 安装Maemo SDK

   这部分的内容: 前言 什么是Scratchbox? Scratchbox的组成 安装的前提条件 自动安装Scratchbox 自动安装Maemo SDK  前言这部分主要介绍安装开发环境以及其先决条件。Maemo SDK含有开发应用的库和工具。这个SDK必须安装在一个称作Scratchbox的开

Linux智能手机--cuijpus的专栏 3587

2025最强MaruOS开发指南:从环境搭建到系统构建的完整实践

Maru OS是一款创新的开源项目,让你的手机变身为强大的PC。本指南将带你从环境搭建到系统构建,全面掌握MaruOS开发的核心技能,轻松实现"手机即电脑"的终极体验。 ## 🚀 为什么选择Maru OS开发? Maru OS通过将Android与Linux桌面环境完美融合,开创了移动设备的全新使用方式。开发者可以利用这一独特架构,为用户打造无缝的跨设备体验。无论是个人学习还是商业项目,Ma

gitblog_00605的博客 445

如何创建Maemo应用程序

http://wiki.forum.nokia.com/index.php?title=%E5%A6%82%E4%BD%95%E5%88%9B%E5%BB%BAMaemo%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F

QuietHeart的专栏 624

maemo hildon-desktop(1)

maemo hildon-desktop(1)2011-7-1 15:48:25maemo系统的桌面对应的二进制程序为hildon-desktop.launch这个可以理解成一个框架或者一个容器。他管理系统中所有的GUI程序如果某个GUI程序不在其管理下,某些

845

Maemo Linux手机平台系列分析:11 Maemo平台开发之 异步GConf

  异步GConf 用GConf来监视变化 当监视对象发生变化时,用GConf给通知 用GConf来监视对象的改变在Maemo中,GConf是主要的用于存储一些设置参数的底层软件。下面,我们将会看到如何去扩展GConf,使它能够更适合于异步方式工作,特别是实现一些服务时,如果把握GConf的使用。 这些情况下需要使用GConf: 1 你的服务

Linux智能手机--cuijpus的专栏 1202

关于maemo Desktop/HomeUI自己收集的资料总结

1.How to write Hildon Desktop plugins for maemohttp://test.maemo.org/platform/docs/howtos/tutorial_desktop_plugins_bora.html#examples 2,Maemo Chinook 4.0.x Tutorialhttp://maemo.org/developme

QuietHeart的专栏 751

BLUEZ:使用DBUS列出所有有效的控制器(controller)

使用"GetManagedObjects"方法获取蓝牙控制器列表。 使用GDBUS: /* * hci_list_gdbus.c - List bluetooth controllers using GDBUS * - The example uses GDBUS to get the list of bluetooth controllers using DBUS * interfaces provided by bluez * - If any controller is fou

专注嵌入式领域 1710
上一篇: Maemo Linux手机平台系列分析:7 Maemo平台开发之LibOSSO
下一篇: 联想集团不玩手机了,卖掉!
testhw
博客等级 码龄19年 172粉丝 183原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值