本篇涉及的知识:
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 char beijing_dbus_interface_name[] = {"world.china.beijing"}; //dbus接口名
const char beijing_dbus_object_name[] = {"/world/china/beijing"}; //dbus对象名
const char property_interface_name[] = {"org.freedesktop.DBus.Properties"}; //property接口名
GMainLoop *loop = NULL;
GDBusConnection *global_connection = NULL;
const char property_operation_name[] = {"Population"}; //围绕该属性做读写操作
//函数声明
void property_get_operation_sync();
void property_set_operation_sync();
void property_get_operation_async();
void property_get_all_operation_async();
void property_changed_listen();
/** 测试目标:同步连接dbus、同步设置dbus Property、异步设置/获取dbus Property
* 监听dbus Property改变的信号
*/
int main(){
//1. 创建主循环
loop = g_main_loop_new(NULL,FALSE);
//2. 获取session dbus connection (因为我们的服务是创建在session dbus总线的,而不是system dbus总线)
global_connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
//3. 同步方式获取属性初始值
property_get_operation_sync();
//4. 监控dbus服务的属性值改变
property_changed_listen();
//5. 同步方式设置属性值
property_set_operation_sync();
//6. 异步方式获取修改后的属性值
property_get_operation_async();
//7. 异步方式获取dbus服务的所有属性值
property_get_all_operation_async();
//8. 启动主循环
g_main_loop_run(loop);
return 0;
}
//同步方法设置某个属性值
void property_set_operation_sync(){
GVariant* result = NULL;
GVariant* parameters = NULL; //Set方法的参数
const GVariantType *reply_type = NULL; //Set函数的返回值类型为NULL;
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NO_AUTO_START;
int timeout = 5000; //超时5秒自动退出
GError *error = NULL; //捕捉错误信息
//Set函数有三个参数,类型分别是String, String, Variant
parameters = g_variant_new("(ssv)", beijing_dbus_interface_name, property_operation_name, g_variant_new_double(10.20)); //设置Beijing的popution属性值为10.20,不需要释放
result = g_dbus_connection_call_sync(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, property_interface_name,
"Set", parameters, reply_type, flags, timeout, NULL, &error);
if(error){
printf("[property-set-sync] %s\n",error->message);
g_error_free(error);
return;
}
//释放内存
if(result){
g_variant_unref(result);
result = NULL;
}
}
//同步方法获取某个属性值
void property_get_operation_sync(){
GVariant* result = NULL;
GVariant* parameters = NULL; //Get方法的参数
const GVariantType *reply_type = G_VARIANT_TYPE("(v)"); //Get函数的返回值类型为"(v)";
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NO_AUTO_START;
int timeout = 5000; //超时5秒自动退出
GError *error = NULL; //捕捉错误信息
double property_value = -1;
//Get方法需要2个参数:接口名、属性名
parameters = g_variant_new("(ss)", beijing_dbus_interface_name, property_operation_name); //获取Beijing的population属性值
result = g_dbus_connection_call_sync(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, property_interface_name,
"Get", parameters, reply_type, flags, timeout, NULL, &error);
if(error){
printf("[property-get-sync] %s\n",error->message);
g_error_free(error);
return;
}
if(result){
GVariant *value = NULL;
g_variant_get(result,"(v)", &value); //Get函数返回值是变体Variant类型
property_value = g_variant_get_double(value); //将变体Variant类型转为Double类型
g_variant_unref(value);
g_variant_unref(result);
result = NULL;
}
printf("[property-get-sync] population=%lf\n",property_value);
}
/** 异步获取某个属性值的回调函数、演示Get函数的返回值处理方式
*/
void property_get_operation_async_callback(GObject* object, GAsyncResult *ret, gpointer data){
GError *error = NULL;
double property_value = -1;
GVariant* result = NULL;
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), ret, &error);
if(error){
printf("[property-get-async] %s\n",error->message);
g_error_free(error);
return;
}
if(result){
GVariant *value = NULL;
g_variant_get(result,"(v)", &value); //Get函数返回值是Variant
property_value = g_variant_get_double(value); //Variant转Double
g_variant_unref(value);
g_variant_unref(result);
result = NULL;
}
printf("[property-get-async] population=%lf\n",property_value);
}
/** 异步获取某个属性值、演示Get函数的参数以及用法
*/
void property_get_operation_async(){
GVariant* parameters = NULL;
const GVariantType *reply_type = G_VARIANT_TYPE("(v)"); //Get函数的返回值类型为"(v)";
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NO_AUTO_START;
int timeout = 5000; //超时5秒自动退出
parameters = g_variant_new("(ss)", beijing_dbus_interface_name, property_operation_name);
g_dbus_connection_call(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, property_interface_name,
"Get", parameters, reply_type, flags, timeout, NULL, property_get_operation_async_callback, NULL);
}
/** 异步获取所有属性值的方法的回调函数、演示GetAll函数的返回值用法
*/
void property_get_all_operation_async_callback(GObject *object, GAsyncResult* ret, gpointer data){
GError *error = NULL;
GVariant* result = NULL;
GVariantIter *iter = NULL; //迭代器,用于遍历循环GetAll函数的返回值
const char* key;
GVariant *value;
result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), ret, &error);
if(error){
printf("[property-get-all-async] %s\n",error->message);
g_error_free(error);
return;
}
g_variant_get(result, "(a{sv})", &iter);
//轮询打印Dict里的每个键值对
while(g_variant_iter_loop(iter, "{&sv}", &key, &value)){
if(g_variant_is_of_type(value, G_VARIANT_TYPE("d"))){
printf("<key,value> = <%s,%lf>\n",key, g_variant_get_double(value));
}else{
printf("<key,value> = <%s,%s>\n",key, g_variant_get_string(value, NULL));
}
}
//释放内存
g_variant_iter_free(iter);
g_variant_unref(result);
}
/** 异步查询dbus服务的对象的所有属性值、演示GetAll函数的参数以及用法
*/
void property_get_all_operation_async(){
GVariant* parameters = NULL;
const GVariantType *reply_type = G_VARIANT_TYPE("(a{sv})"); //Get函数的返回值类型为"Dict of {String,Variant}";
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NO_AUTO_START;
int timeout = 5000; //超时5秒自动退出
parameters = g_variant_new("(s)", beijing_dbus_interface_name); //GetAll函数只有一个参数: dbus接口名
g_dbus_connection_call(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, property_interface_name,
"GetAll", parameters, reply_type, flags, timeout, NULL, property_get_all_operation_async_callback, NULL);
}
/** 监听属性改变的回调函数、获取发生改变的具体属性名
*/
void property_changed_callback (GDBusConnection *connection,const gchar *sender_name,const gchar *object_path,const gchar *interface_name,
const gchar *signal_name,GVariant *parameters, gpointer data){
GVariantIter iter;
const char *key = NULL;
GVariant *props, *value;
//NULL 对应 s
//props 对应 @a{sv}
//NULL 对应 *
g_variant_get(parameters, "(s@a{sv}*)", NULL, &props, NULL);
g_variant_iter_init(&iter, props);
while(g_variant_iter_loop(&iter, "{sv}", &key, &value)){
printf("[property-changed] %s had changed!\n", key);
}
g_variant_unref(props);
}
/** 监控属性值改变
*/
void property_changed_listen(){
const char* unique_name = NULL;
//unique_name = g_dbus_connection_get_unique_name(global_connection);//这种方式获取到的UniqueName不可用,因为它无法捕捉到信号
//g_dbus_connection_signal_subscribe(global_connection, unique_name, property_interface_name,
g_dbus_connection_signal_subscribe(global_connection, NULL, property_interface_name,
"PropertiesChanged", beijing_dbus_object_name, beijing_dbus_interface_name,
G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback)property_changed_callback,
NULL, NULL);
}