下一篇: GDBus之信号使用
本篇涉及到的知识:
1.dbus Method的同步与异步使用
2.dbus Method的参数如何传递
3.dbus Method的返回值如何处理
method-test.c 文件
#include <stdio.h>
#include <signal.h>
#include <glib.h> //提供GMainLoop类型定义、g_new0()函数声明
#include <gio/gio.h> //提供GDBusConnection类型定义、g_dbus_...等函数声明
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;
//函数声明
void dbus_method_call_async_set_population();
void dbus_method_call_sync_get_all_district();
void dbus_method_call_async_set_population_callback(GObject* object, GAsyncResult* res, gpointer data);
void signal_sigint_handler();
int main(){
signal(SIGINT, signal_sigint_handler);
loop = g_main_loop_new(NULL,FALSE); //创建主循环,NULL表示没有上下文,FALSE表示不立即运行
//1. 使用同步方式获取session dbus连接
global_connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
//2. 异步调用dbus Method
dbus_method_call_async_set_population();
//3. 同步调用dbus Method
dbus_method_call_sync_get_all_district();
g_main_loop_run(loop); //运行主循环
return 0;
}
/** 异步调用dbus方法示例、参数传递示例
* 调用beijing dbus服务的SetPopulation方法
*/
void dbus_method_call_async_set_population(){
GVariant *parameters = g_variant_new("(d)", 1.23); //SetPopulation函数接受一个Double类型的参数
const GVariantType *reply_type = G_VARIANT_TYPE("()"); //SetPopulation函数无返回值
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NONE;
int timeout = 5000; //超时5秒自动退出
//dbus Method异步调用示例
g_dbus_connection_call(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, beijing_dbus_interface_name,
"SetPopulation", parameters, reply_type, flags, timeout, NULL,
(GAsyncReadyCallback)dbus_method_call_async_set_population_callback, NULL);
}
/** 同步调用beijing dbus的GetAllDistrict方法
* 演示如何处理dbus Method返回的复杂类型
*/
void dbus_method_call_sync_get_all_district(){
GError *error = NULL;
GVariant *result = NULL;
GVariant* parameters = NULL; //该dbus Method不需要参数(参数为NULL)
const GVariantType *reply_type = G_VARIANT_TYPE("(as)");//该dbus Method返回值为一个字符串数组(a表示数组 s表示是字符串)
GDBusCallFlags flags = G_DBUS_CALL_FLAGS_NONE;
int timeout = 5000; //超时5秒自动退出
result = g_dbus_connection_call_sync(global_connection, beijing_dbus_server_name, beijing_dbus_object_name, beijing_dbus_interface_name,
"GetAllDistrict", parameters, reply_type, flags, timeout, NULL, &error);
if(error){
printf("[dbus-method-call-sync]:%s\n",error->message);
g_error_free(error);
error = NULL;
return;
}
//处理方法返回值
int index = 0;
char* tmp = NULL;
char **all_districts = NULL;
g_autoptr(GVariantIter) iter = NULL; //智能指针
all_districts = g_new0(char*, 17); //北京16个区,我们分配17个地址
g_variant_get(result, "(as)", &iter); //获取指向dbus Method返回值的迭代器
/*&s 表示直接使用已有数据内存的地址,不需要额外分配内存*/
while(g_variant_iter_loop(iter, "&s", &tmp))//如果"&s"替换为"s"则会乱码
all_districts[index++] = tmp;
//查看dbus Method通信的结果
for(index = 0; all_districts[index]; ++index){
printf("%s ",all_districts[index]);
}
printf("\n");
g_free(all_districts); //释放二维数组内存
g_variant_unref(result); //释放变体类型
result = NULL;
}
/** 异步调用dbus Method的回调函数
* 用于查看Method是否调用成功,失败了可以查看error->message错误信息
* 也可增加其他的业务处理逻辑
*/
void dbus_method_call_async_set_population_callback(GObject* object, GAsyncResult* res, gpointer data){
GError* error = NULL;
GVariant *value = NULL;
printf("[dbus-method-async-call] call setPopulation finished\n");
value = g_dbus_connection_call_finish(global_connection, res, &error);
if(error){
printf("[dbus-close] %s\n",error->message);
g_error_free(error);
}
if(value){
g_variant_unref(value);
return;
}
}
/** 处理linux操作系统的SIGINT信号(Ctl+C组合键)
* 用于退出主循环,释放内存,退出程序
*/
void signal_sigint_handler(){
GError *error = NULL;
if(global_connection && G_IS_DBUS_CONNECTION(global_connection)){
g_dbus_connection_close_sync(global_connection,NULL,&error);
global_connection = NULL;
}
if(error){
printf("[dbus-close] %s\n",error->message);
g_error_free(error);
}
if(loop){
g_main_loop_quit(loop);
g_main_loop_unref(loop);
loop = NULL;
}
}