DBUS概述
DBus(D-Bus)是一个在不同程序之间传递消息的系统总线。DBus为不同的程序之间提供了一种通信机制,这种通信制可以在不需要知道对方程序的情况下进行通信。
DBus可以使用多种编程语言来开发,包括C、C++、Python、Java等。在这里,我们以C语言为例来讲解DBus的开发过程。
DBus的主要特点包括:
1. 语言独立性:DBus支持多种编程语言,包括C、C++、Python、Java等。
2. 灵活性:DBus的通信机制非常灵活,支持广播、点对点、异步和同步通信。
3. 安全性:DBus提供了一些安全机制,如身份验证和权限控制,以确保通信的安全性。
4. 可扩展性:DBus支持多个会话总线,可以用于在多个计算机之间进行通信,同时还可以在运行时动态添加和删除对象。
DBus接口(DBus interface)是DBus对象(DBus object)上的一个虚拟界面,它定义了可以通过DBus对象访问的DBus方法、DBus信号和DBus属性。DBus接口使用DBus编程语言中的XML描述符来定义,它具有以下特点:
* DBus接口具有一个名称,它使用类似于UNIX文件系统路径的命名方式来组织,例如 “com.example.Calculator”。
* DBus接口可以继承其他DBus接口。
* DBus接口可以定义DBus方法,DBus方法可以具有零个或多个输入参数和零个或一个输出参数。
* DBus接口可以定义DBus信号,DBus信号是DBus对象发出的一种事件通知,它可以包含任意数量的参数。
* DBus接口可以定义DBus属性,DBus属性是DBus对象的状态信息,它可以被读取或写入。DBus属性可以是只读、可写或读写的。
DBus接口通常是DBus应用程序的主要组成部分,因为它定义了DBus对象的可用功能。在DBus编程中,我们通常使用DBus接口来定义DBus对象的行为,然后在DBus对象上注册DBus接口。这样,在DBus客户端与DBus对象进行通信时,DBus客户端可以查询DBus接口以了解DBus对象的功能,并调用DBus方法、监听DBus信号和读取或写入DBus属性。
DBus的开发步骤
DBus的开发过程可以分为以下几个步骤:
1. 创建DBus连接
在使用DBus进行通信之前,需要先创建一个DBus连接。DBus连接可以通过函数 dbus_bus_get() 来获取。
2. 注册DBus对象
在DBus中,所有的对象都必须先注册才能被其他程序访问。DBus对象可以使用 dbus_connection_register_object() 函数进行注册。
3. 创建DBus消息
在DBus中,消息是所有通信的基本单元。DBus消息可以使用 dbus_message_new() 函数进行创建。
4. 发送DBus消息
创建好DBus消息之后,需要使用 dbus_connection_send() 函数将消息发送出去。
5. 接收DBus消息
在DBus中,需要使用事件循环来等待消息的到来。DBus消息可以使用 dbus_connection_pop_message() 函数来获取。
6. 处理DBus消息
获取到DBus消息之后,需要对消息进行解析和处理。
7. 清理DBus连接
在程序退出之前,需要释放所有的DBus资源。DBus连接可以使用 dbus_connection_unref() 函数来释放。
下面我们通过一个简单的示例来演示DBus的开发过程。示例程序
在本例中,我们将创建一个DBus服务,这个服务可以将两个整数相加并返回结果。
1. 创建DBus连接
首先,我们需要创建DBus连接。DBus连接可以通过函数 dbus_bus_get() 来获取。
DBusError err;
DBusConnection* conn;
dbus_error_init(&err);
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err))
{
printf("DBus connection error: %s\n", err.message);
dbus_error_free(&err);
return-1;
}
2.注册DBus对象
我们需要将一个对象注册到DBus上。在本例中,我们将一个对象 /com/example/Calculator 注册到DBus上,并定义两个方法 Add 和 Quit。
DBusObjectPathVTable vtable = { .message_function = &dbus_message_handler };
DBusError err;
DBusObjectPath* path;
DBusObject* object;
dbus_error_init(&err);
path = dbus_object_path_new("/com/example/Calculator");
object = dbus_object_new(conn, path);
dbus_connection_register_object(conn, path, &vtable, object);
if(dbus_error_is_set(&err))
{
printf("DBus object registration error: %s\n", err.message);
dbus_error_free(&err);return-1;
}
在上述代码中,我们定义了一个 DBusObjectPathVTable 结构体,用于注册DBus对象时的消息处理函数 dbus_message_handler()。在本例中,我们需要实现两个方法 Add 和 Quit,因此我们需要在消息处理函数中对这两个方法进行处理。
DBusHandlerResultdbus_message_handler(DBusConnection* conn, DBusMessage* msg,void* user_data)
{
if(dbus_message_is_method_call(msg,"com.example.Calculator","Add"))
{
// 处理 Add 方法
DBusMessageIter iter;inta, b, sum;
dbus_message_iter_init(msg, &iter);
dbus_message_iter_get_basic(&iter, &a);
dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, &b);
sum = a + b;
DBusMessage* reply = dbus_message_new_method_return(msg);
DBusMessageIter reply_iter; dbus_message_iter_init_append(reply, &reply_iter);
dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &sum);
dbus_connection_send(conn, reply,NULL);
dbus_message_unref(reply);
return DBUS_HANDLER_RESULT_HANDLED;
}else if(
dbus_message_is_method_call(msg,"com.example.Calculator","Quit"))
{
// 处理 Quit 方法
dbus_connection_close(conn);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
在上述代码中,我们首先判断消息是否为 Add 方法的调用。如果是,我们就从消息中获取两个整数 a 和 b,然后将它们相加得到 sum。接下来,我们将 sum 封装到一个新的DBus消息中,并将这个消息通过 dbus_connection_send() 函数发送出去。
如果消息是 Quit 方法的调用,我们就通过 dbus_connection_close() 函数关闭DBus连接。
3.创建DBus消息
在本例中,我们需要创建一个DBus消息来调用 Add 方法。
DBusMessage* msg = dbus_message_new_method_call("com.example.Calculator","/com/example/Calculator","com.example.Calculator","Add");
DBusMessageIter args;
dbus_message_iter_init_append(msg, &args);
dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &a);
dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &b);
在上述代码中,我们首先创建了一个DBus消息 msg,然后将消息类型设置为方法调用,方法名为 Add,对象路径为 /com/example/Calculator。
接下来,我们使用 dbus_message_iter_init_append() 函数初始化一个DBus消息迭代器,并将两个整数 a 和 b 追加到DBus消息中。
4. 发送DBus消息
创建好DBus消息之后,我们可以使用 dbus_connection_send() 函数将消息发送出去。
DBusPendingCall* pending;
dbus_connection_send_with_reply(conn, msg, &pending,-1);
dbus_connection_flush(conn);
在上述代码中,我们使用 dbus_connection_send_with_reply() 函数将DBus消息发送出去,并等待DBus服务器的应答。应答消息将存储在 pending 变量中。我们还可以使用 dbus_connection_flush() 函数强制刷新DBus连接,以确
保消息被发送出去。
5. 接收DBus应答
当DBus服务器收到DBus消息并处理完成后,会通过DBus连接向客户端发送应答消息。在上述代码中,我们使用 dbus_pending_call_set_notify() 函数注册回调函数 dbus_reply_handler()。当DBus应答消息到达时,回调函数将被调用,并将DBus应答消息中的整数 sum 传递给它。
6. 处理DBus应答
当DBus应答消息到达时,回调函数 dbus_reply_handler() 将被调用。在本例中,我们需要从DBus应答消息中获取整数 sum 并打印出来。
void dbus_reply_handler(DBusPendingCall* pending,void* user_data)
{
int* sum = (int*)user_data;
DBusMessage* reply = dbus_pending_call_steal_reply(pending);
DBusMessageIter iter;
if(reply)
{
if(dbus_message_iter_init(reply, &iter))
{
dbus_message_iter_get_basic(&iter, sum);
printf("The sum is: %d\n", *sum);
}
dbus_message_unref(reply);
}
dbus_pending_call_unref(pending);
}
在上述代码中,我们首先从回调函数参数 user_data 中获取整数指针 sum,然后使用 dbus_pending_call_steal_reply() 函数从DBus应答消息中提取应答消息。如果应答消息存在,我们就从消息中获取整数 sum 并打印出来。最后,我们释放DBus应答消息和DBus挂起调用。
完整示例代码
#include<stdio.h>
#include<stdlib.h>
#include<dbus/dbus.h>
DBusHandlerResult dbus_message_handler(DBusConnection* conn, DBusMessage* msg,void* user_data)
{
if(dbus_message_is_method_call(msg,"com.example.Calculator","Add"))
{
// 处理 Add 方法
DBusMessageIter iter;
inta, b, sum;
dbus_message_iter_init(msg, &iter);
dbus_message_iter_get_basic(&iter, &a);
dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, &b);
sum = a + b; DBusMessage* reply = dbus_message_new_method_return(msg);
DBusMessageIter reply_iter;
dbus_message_iter_init_append(reply, &reply_iter);
dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &sum);
dbus_connection_send(conn, reply,NULL);
dbus_message_unref(reply);
returnDBUS_HANDLER_RESULT_HANDLED;
}else if(
dbus_message_is_method_call(msg,"com.example.Calculator","Quit")){
// 处理 Quit 方法
dbus_connection_close(conn);
returnDBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
voiddbus_reply_handler(DBusPendingCall* pending,void* user_data)
{
int* sum = (int*)user_data;
DBusMessage* reply =dbus_pending_call_steal_reply(pending);
DBusMessageIter iter;
if (reply)
{
if (dbus_message_iter_init(reply, &iter))
{
dbus_message_iter_get_basic(&iter, sum);
printf("The sum is: %d\n", *sum);
}
dbus_message_unref(reply);
}
dbus_pending_call_unref(pending);
}
int main()
{
DBusError error;
DBusConnection* conn;
DBusMessage* msg;
DBusPendingCall* pending;
int sum = 0;
dbus_error_init(&error);
// 建立到系统DBus总线的连接
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "Error connecting to system bus: %s\n", error.message);
dbus_error_free(&error);
return EXIT_FAILURE;
}
// 注册对象路径和消息处理函数
dbus_bus_request_name(conn, "com.example.Calculator", 0, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "Error requesting name: %s\n", error.message);
dbus_error_free(&error);
return EXIT_FAILURE;
}
dbus_connection_register_object_path(conn, "/com/example/Calculator", &dbus_interface, NULL);
// 创建DBus消息
msg = dbus_message_new_method_call("com.example.Calculator", "/com/example/Calculator", "com.example.Calculator", "Add");
// 将参数添加到DBus消息中
DBusMessageIter iter;
dbus_message_iter_init_append(msg, &iter);
int a = 2, b = 3;
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &a);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &b);
// 发送DBus消息并等待应答
dbus_connection_send_with_reply(conn, msg, &pending, -1);
dbus_message_unref(msg);
dbus_pending_call_set_notify(pending, dbus_reply_handler, &sum, NULL);
while (dbus_connection_read_write_dispatch(conn, -1)) {
}
dbus_connection_unref(conn);
return EXIT_SUCCESS;
}
在上述代码中,我们首先建立到系统DBus总线的连接,然后注册对象路径和消息处理函数。接下来,我们创建一个DBus消息,并将参数添加到消息中。然后,我们使用 dbus_connection_send_with_reply()
函数将DBus消息发送到DBus服务器,并等待应答。在等待期间,我们使用 dbus_connection_read_write_dispatch()
函数循环调用DBus连接以便处理DBus消息。当DBus应答消息到达时,回调函数 dbus_reply_handler()
将被调用。
常用的蓝牙dbus接口
在Linux系统中,蓝牙的实现通常使用DBus进行管理和控制。下面介绍一些常用的蓝牙DBus接口及其功能:
1. org.bluez.Agent1
这个接口用于管理蓝牙代理,实现了蓝牙认证和授权功能。在进行蓝牙配对时,代理程序将被调用来执行认证和授权操作。该接口定义了以下方法:
* RequestConfirmation (in uint32_t, out uint32_t)
* RequestAuthorization (in uint32_t, out uint32_t)
* AuthorizeService (in object path, out boolean)
* Cancel ()
2.org.bluez.Adapter1
这个接口用于管理蓝牙适配器,实现了蓝牙设备的搜索和管理功能。该接口定义了以下方法:
* StartDiscovery ()
* StopDiscovery ()
* GetProperties ()
* SetProperty (in string, in variant)
* GetAllProperties ()
* CreateDevice (in string, out object path)
* RemoveDevice (in object path)
* GetDevice (in object path, out object path)
* GetDevices (out array of object path)
* GetDeviceProperties (in object path, out dict of string variant)
3.org.bluez.Device1
这个接口用于管理蓝牙设备,实现了设备的配对、连接和断开连接等功能。该接口定义了以下方法:
* Connect ()
* Disconnect ()
* Pair ()
* CancelPairing ()
* GetProperties ()
* SetProperty (in string, in variant)
* GetAllProperties ()
* GetServices (out array of object path)
4.org.bluez.MediaTransport1
这个接口用于管理蓝牙音频传输,实现了音频的传输和控制功能。该接口定义了以下方法:
* SetConfiguration (in dict of string variant)
* SelectConfiguration (in dict of string variant)
* ClearConfiguration ()
* Release ()
* Acquire (out string)
* GetProperties ()
* SetProperty (in string, in variant)
* GetAllProperties ()
这些接口定义了蓝牙管理和控制的基本方法,开发人员可以通过DBus API来调用这些方法实现蓝牙应用程序的开发。需要注意的是,这些接口在不同版本的蓝牙协议中可能存在差异,开发人员需要根据具体情况进行调整。
初试dbus调用蓝牙接口
在Linux系统中,DBus API可以使用C语言或其他编程语言进行调用。下面以C语言为例介绍如何使用DBus API调用这些接口。
1. 首先需要包含DBus头文件
#include<dbus/dbus.h>
2.初始化DBus连接
DBusError error;
DBusConnection* conn;
dbus_error_init(&error);
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if(dbus_error_is_set(&error))
{
printf("Error connecting to the daemon bus: %s\n", error.message);
dbus_error_free(&error);
return;
}
3.调用DBus方法
DBusMessage* msg;
DBusMessageIter args;
DBusPendingCall* pending;
msg = dbus_message_new_method_call("org.bluez","/org/bluez/hci0","org.bluez.Adapter1","StartDiscovery");
if(!msg) {
printf("Error creating dbus message\n");
return;
}
if(!dbus_connection_send_with_reply(conn, msg, &pending,-1))
{
printf("Error sending dbus message\n");
dbus_message_unref(msg);
return;
}
dbus_connection_flush(conn);
dbus_message_unref(msg);
dbus_pending_call_block(pending);
msg = dbus_pending_call_steal_reply(pending);
if(msg)
{
dbus_message_iter_init(msg, &args);
dbus_pending_call_unref(pending);
dbus_message_unref(msg);
}
在上面的例子中,我们调用了org.bluez.Adapter1接口的StartDiscovery方法。其中,dbus_message_new_method_call函数用于创建DBus方法调用消息,第一个参数是服务名称,第二个参数是对象路径,第三个参数是接口名称,第四个参数是方法名称。dbus_connection_send_with_reply函数用于发送DBus消息并等待回复,第一个参数是DBus连接,第二个参数是DBus消息,第三个参数是DBus异步调用,第四个参数是超时时间。dbus_pending_call_block函数用于阻塞DBus调用直到接收到回复,dbus_pending_call_steal_reply函数用于获取DBus调用的回复。
通过以上步骤,我们可以使用DBus API调用蓝牙相关的接口实现蓝牙应用程序的开发。需要注意的是,DBus API的调用方式和参数类型在不同版本的DBus协议中可能存在差异,开发人员需要根据具体情况进行调整。
一些难点注意
1.D-Bus消息的结构
DBus消息是由一系列DBus类型构成的结构,开发人员需要了解DBus消息的类型和结构,才能正确地创建和解析DBus消息。DBus类型包括基本类型(如整型、字符串、布尔型等)和复合类型(如结构体、数组、字典等)。DBus消息的结构和类型定义在DBus规范中,开发人员需要根据规范进行编程。
2. DBus连接和线程安全
DBus连接是DBus消息传输的基础,开发人员需要了解DBus连接的创建、销毁和使用方法。同时,DBus连接还涉及到线程安全的问题,因为DBus连接是多线程共享的资源。开发人员需要了解DBus连接的线程安全特性,合理地管理DBus连接的生命周期和使用方法,避免出现线程安全问题。
3. DBus错误处理
DBus API的调用过程中,可能会出现各种错误,包括DBus连接错误、DBus消息格式错误、DBus方法调用错误等。开发人员需要了解DBus错误处理的方法,正确地捕获和处理DBus错误,避免出现程序崩溃等严重问题。
4. DBus调试工具
在DBus开发过程中,可能会遇到DBus调用失败、消息格式错误等问题,需要进行调试。DBus提供了一些调试工具,如dbus-monitor、dbus-send等,开发人员需要了解这些工具的使用方法,以便快速定位和解决DBus调试问题。
总之,在进行Linux C中DBus开发时,开发人员需要深入了解DBus规范、DBus API和DBus调试工具,才能够高效地进行DBus开发。同时,需要注意DBus连接的线程安全问题和DBus错误处理问题,以提高程序的可靠性和稳定性。
GDBUS概述
gdbus是Glib库提供的DBus API的实现,是基于DBus C API的一层封装。Glib是GNOME桌面环境的核心库,提供了许多常用的工具和组件,如事件循环、线程、内存管理、字符串处理、数据结构等。
gdbus封装了DBus API,提供了一组更易用的API,比DBus C API更加简洁、直观、安全和高效。使用gdbus开发DBus应用程序,可以大大提高开发效率和代码质量。
gdbus的特点包括:
1. 对DBus API进行了封装,提供了更易用的API接口,简化了DBus开发的过程和代码量。
2. 提供了自动类型转换和参数检查机制,避免了DBus API的错误使用。
3. 使用Glib的事件循环机制,提供了异步DBus调用的支持,能够更好地处理DBus的异步消息。
4. 提供了DBus接口的代理机制,支持DBus的远程调用。
总之,gdbus是Glib库提供的DBus API的实现,是DBus开发的一种高层次的抽象,能够大大简化DBus开发的过程和代码量,并提供了异步DBus调用和DBus远程调用的支持。
GDBUS API的介绍
- g_dbus_connection_new_sync: 此函数用于创建新的GDBusConnection连接。它需要指定一个连接名和一个连接地址,还可以指定DBus连接的选项。
- g_dbus_connection_call_sync: 此函数用于在给定的GDBus连接上同步调用远程对象的方法。它需要指定对象的名称、接口名称、方法名称和方法的参数。此外,还可以指定调用超时时间和DBus调用的选项。
- g_dbus_proxy_new_sync: 此函数用于创建一个新的GDBus代理。它需要指定一个GDBusConnection连接、一个DBus代理的名称、代理接口的名称以及DBus代理的选项。
- g_dbus_proxy_call_sync: 此函数用于在给定的GDBus代理上同步调用远程对象的方法。它需要指定方法名称、方法的参数、调用超时时间和DBus调用的选项。
- g_dbus_proxy_set_default_timeout: 此函数用于设置DBus调用的默认超时时间(以毫秒为单位)。这个超时时间将应用于调用同步方法和在DBus代理上调用异步方法时未指定超时时间的调用。
- g_dbus_proxy_call: 此函数用于在给定的GDBus代理上异步调用远程对象的方法。它需要指定方法名称、方法的参数、DBus调用的选项以及一个回调函数来处理异步调用结果。
- g_dbus_proxy_call_finish: 此函数用于完成由g_dbus_proxy_call启动的异步DBus调用,并返回调用结果。
- g_dbus_proxy_new_for_bus_sync: 此函数用于在指定的DBus总线上创建一个新的GDBus代理。它需要指定DBus总线类型、DBus代理的名称、代理接口的名称以及DBus代理的选项。
- g_dbus_connection_new_for_address_sync():建立与DBus daemon的连接。在bluez开发中,我们需要通过该API建立与BlueZ daemon的连接。
- g_dbus_connection_register_object():用于注册一个对象到DBus系统总线上。在bluez开发中,我们可以用它将自定义的蓝牙服务以及属性注册到BlueZ daemon上。
- g_dbus_connection_call_sync():用于同步调用DBus方法。在bluez开发中,我们可以用它来调用BlueZ daemon上的方法,比如获取蓝牙设备、服务或特征的属性等。
- g_dbus_connection_signal_subscribe():用于订阅DBus signal。在bluez开发中,我们可以用它来订阅蓝牙设备的状态改变、蓝牙服务的添加或删除、蓝牙特征的值变化等事件。
- g_dbus_proxy_new_sync():用于创建一个代理对象。在bluez开发中,我们可以用它来创建一个代理对象,从而方便地操作蓝牙设备、服务或特征。
- g_dbus_proxy_call_sync():用于同步调用代理对象上的DBus方法。在bluez开发中,我们可以用它来调用代理对象上的方法,比如读取或写入蓝牙特征的值。
- g_dbus_proxy_get_property():用于获取代理对象上的属性值。在bluez开发中,我们可以用它来获取蓝牙设备、服务或特征的属性值。
- g_dbus_proxy_set_property():用于设置代理对象上的属性值。在bluez开发中,我们可以用它来设置蓝牙设备、服务或特征的属性值。
GDBUS的开发步骤
1.定义DBus接口
定义DBus接口,包括接口名称、方法名称、参数等,可以通过GDBusNodeInfo结构体来描述DBus接口。GDBusNodeInfo结构体包含一个或多个GDBusInterfaceInfo结构体,每个GDBusInterfaceInfo结构体描述一个DBus接口。可以使用GDBusNodeInfoBuilder结构体来动态地创建GDBusNodeInfo结构体。
2.注册DBus接口
将DBus接口注册到DBus总线上,可以通过GDBusConnection结构体的g_dbus_connection_register_object()函数来实现。该函数的参数包括DBus总线连接、对象路径、DBus接口信息、DBus方法回调函数等。
3.连接DBus总线
通过g_bus_get_sync()函数连接DBus总线。该函数返回一个GDBusConnection结构体指针,可以通过该结构体指针来发送DBus消息、注册DBus接口、监听DBus信号等。
4.发送DBus消息
使用GDBusConnection结构体的g_dbus_connection_send_message_with_reply_sync()函数或g_dbus_connection_send_message_with_reply_async()函数来发送DBus消息。这些函数的参数包括DBus总线连接、DBus消息、DBus消息类型、超时时间等。
5. 接收DBus消息
使用GDBusConnection结构体的g_dbus_connection_signal_subscribe()函数来接收DBus消息。该函数的参数包括DBus总线连接、DBus接口名称、信号名称、回调函数、用户数据等。
6. 处理DBus方法调用
使用GDBusConnection结构体的g_dbus_connection_register_object()函数注册DBus方法回调函数。当DBus客户端调用DBus方法时,DBus守护进程将会调用相应的DBus方法回调函数。可以在DBus方法回调函数中处理DBus方法调用并返回结果。
7. 启动事件循环
使用g_main_loop_run()函数启动事件循环,以便接收DBus消息、处理DBus方法调用等。
以上是使用gdbus开发DBus应用程序的基本步骤。需要注意的是,gdbus是Glib库提供的DBus API的实现,因此需要安装Glib库和gio库才能进行gdbus开发。
GDBus调用蓝牙BlueZ 接口
1.创建 GDBus 连接
GDBusConnection *bus =NULL;
GError *error =NULL;
bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL, &error);
if(!bus)
{
g_error("Failed to get system bus: %s", error->message);
g_error_free(error);
return;
}
2.创建 GDBus 代理对象
#define BLUEZ_SERVICE "org.bluez"
#define ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter1"
GDBusProxy *adapter_proxy =NULL;
GError *error =NULL;
// 这里的 hci0 根据实际情况来修改
adapter_proxy = g_dbus_proxy_new_sync( bus, G_DBUS_PROXY_FLAGS_NONE,NULL, BLUEZ_SERVICE,"/org/bluez/hci0", ADAPTER_INTERFACE,NULL, &error);
if(!adapter_proxy)
{
g_error("Failed to create adapter proxy: %s", error->message);
g_error_free(error);
return;
}
3.调用 GDBus 代理对象的方法
GVariant *result =NULL;
GError *error =NULL;
result = g_dbus_proxy_call_sync( adapter_proxy,"StartDiscovery",NULL, G_DBUS_CALL_FLAGS_NONE,-1,NULL, &error);
if(!result)
{
g_error("Failed to call StartDiscovery: %s", error->message);
g_error_free(error);
return;
}
完整示例代码
#include<gio/gio.h>
#define BLUEZ_SERVICE "org.bluez"
#define ADAPTER_INTERFACE BLUEZ_SERVICE ".Adapter1"
int main(intargc,char*argv[])
{
// 创建 GDBus 连接
GDBusConnection *bus =NULL;
GError *error =NULL;
bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL, &error);
if(!bus)
{
g_error("Failed to get system bus: %s", error->message);
g_error_free(error);
return 1;
}
// 创建 GDBus 代理对象
GDBusProxy *adapter_proxy =NULL;
// 这里的 hci0 根据实际情况来修改
adapter_proxy = g_dbus_proxy_new_sync( bus, G_DBUS_PROXY_FLAGS_NONE,NULL, BLUEZ_SERVICE,"/org/bluez/hci0", ADAPTER_INTERFACE,NULL, &error);
if(!adapter_proxy)
{
g_error("Failed to create adapter proxy: %s", error->message); g_error_free(error);
return 1;
}
// 调用 GDBus 代理对象的方法
GVariant *result =NULL;
result = g_dbus_proxy_call_sync( adapter_proxy,"StartDiscovery",NULL, G_DBUS_CALL_FLAGS_NONE,-1,NULL, &error);
if(!result)
{
g_error("Failed to call StartDiscovery: %s", error->message);
g_error_free(error);
return 1;
}
g_object_unref(adapter_proxy);
g_variant_unref(result);
g_dbus_connection_unref(bus);
}
对于GDBus方法,我们需要使用GVariant对象来表示参数和返回值。例如,为了调用org.bluez.Adapter1接口的StartDiscovery方法,我们需要使用以下代码:
GError *error =NULL;
GVariant *result = g_dbus_connection_call_sync( connection,"org.bluez","/org/bluez/hci0","org.bluez.Adapter1","StartDiscovery",NULL,NULL, G_DBUS_CALL_FLAGS_NONE,-1,NULL, &error);
if(error !=NULL)
{
g_error("Error calling StartDiscovery: %s", error->message);
}
g_variant_unref(result);
这里的connection是一个GDBusConnection对象,它是通过g_dbus_connection_new_for_address_sync()函数创建的。注意,我们没有传递任何参数给StartDiscovery方法,因为它不需要任何参数。对于需要传递参数的方法,我们需要构造一个GVariant对象来表示参数。例如,为了调用org.bluez.Device1接口的Pair方法,我们可以使用以下代码:
GError *error =NULL;
GVariant *params = g_variant_new("(s)","Keyboard");
// 参数是字符串"Keyboard"
GVariant *result = g_dbus_connection_call_sync( connection,"org.bluez","/org/bluez/hci0/dev_00_11_22_33_44_55","org.bluez.Device1","Pair", params,NULL, G_DBUS_CALL_FLAGS_NONE,-1,NULL, &error);
if(error !=NULL)
{
g_error("Error calling Pair: %s", error->message);
}
g_variant_unref(result);
g_variant_unref(params);