reference :
https://blog.csdn.net/f110300641/article/details/106823611,
https://dbus.freedesktop.org/doc/dbus-specification.html,
Linux进程间通信:dbus的使用(2)—— D-Bus介绍及signal、method测试例程_dbus signal-CSDN博客
D-BUS是一种低开销、易于使用的进程间通信系统(IPC)。
消息总线分为:
特性 | Session Bus | System Bus |
---|---|---|
启动时机 | 用户登录时 | 系统启动时(由 systemd 管理) |
权限 | 用户级权限 | root 权限 |
配置文件 | session.conf ,用户级服务描述文件 |
system.conf ,系统服务描述文件 |
典型应用 | 桌面应用集成(如通知系统) | 硬件事件(如 USB 插入)、系统服务通信 |
地址固定性 | 动态地址(环境变量指定) | 固定地址(/var/run/dbus/system_bus_socket ) |
dbus-daemon(消息总线守护进程 )
dbus-daemon
进程,专门负责管理该会话内的所有消息路由和服务注册。二者是同一实体的逻辑与物理表现。dbus中的消息有四种类型:
signal与method的区别:
连接(Bus name)标识与会话总线的连接,表示一个dbus服务
对象路径(Object Path)唯一标识服务中的对象实例(类似文件路径),标识资源的路径。命名规则:采用斜杠分隔的层次结构,如 /org/kde/Device1
。
接口名称(Interface Name),定义对象的能力契约,包含方法、信号和属性(类似抽象类)。可以被不同的对象实现。采用反向域名格式(如 org.freedesktop.DBus.Properties),需在总线范围内唯一。接口与对象是解耦的,二者名称并不需要严格对应。
方法和信号隶属于接口。
层级关系:
Bus name -》Path-》Interface-》Method/Signal
安装:sudo apt install dbus
包含头文件:#include <dbus/dbus.h>
signal
发送方步骤:
接收方步骤:
method_call & method_reply
被调用方步骤:
建立连接
注册连接名称(必须)
循环监听
解析调用消息并处理
调用方步骤:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus.h> #include <unistd.h>
int send_a_signal(char *sigvalue)
{
// 创建所需变量
DBusError err;
DBusConnection *connection;
DBusMessage *msg;
DBusMessageIter arg;
dbus_uint32_t serial = 0;
int ret;// 步骤1:建立与session bus的连接 dbus_error_init(&err); // 初始化错误结构体 connection = dbus_bus_get(DBUS_BUS_SESSION, &err ); // 获取一个与session bus的连接 if(dbus_error_is_set(&err)){ fprintf(stderr, "ConnectionErr : %s\n", err.message); dbus_error_free(&err); } if(connection == NULL) return -1; // 步骤2:给连接注册一个名字,这个步骤不是必须的
if 1
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Name Err :%s\n", err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return -1;
endif
// 步骤3:发送一个信号 // 创建message,message参数中包含这个信号的路径,接口,以及信号名 if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){ fprintf(stderr, "MessageNULL\n"); return -1; } // 给这个messge具体的内容 dbus_message_iter_init_append(msg, &arg); if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){ fprintf(stderr, "Out OfMemory!\n"); return -1; } // 步骤4: 将信号通过连接发送 if(!dbus_connection_send(connection, msg, &serial)){ fprintf(stderr, "Out of Memory!\n"); return -1; } dbus_connection_flush(connection); printf("Signal Send\n"); // 步骤5: 释放资源。 dbus_message_unref(msg); return 0;
}
int main( int argc, char **argv){
send_a_signal("Hello,world!");
return 0;
}
dbus_connection_send
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
connection
:
DBusConnection*
dbus_bus_get(DBUS_BUS_SESSION/SYSTEM, ...)
获取的会话或系统总线连接对象message
:
DBusMessage*
serial
:
NULL
指针,函数会将消息的唯一序列号写入该地址,用于跟踪消息(如调试),该序列号唯一企鹅递增。该消息的值由dbus内部程序写入,使用者不该写入值。#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus.h> #include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;// 步骤1:建立与session bus的连接 dbus_error_init(&err); connection = dbus_bus_get(DBUS_BUS_SESSION, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "ConnectionError %s\n", err.message); dbus_error_free(&err); } if(connection == NULL) return; // 步骤2:给连接注册一个名称,非必需但推荐 ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "Name Error%s\n", err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return; // 步骤3:添加监听匹配规则 dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err); dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效 if(dbus_error_is_set(&err)){ fprintf(stderr, "Match Error%s\n", err.message); dbus_error_free(&err); } // 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。 while(1){ dbus_connection_read_write(connection, 0); // 非阻塞读写 msg = dbus_connection_pop_message(connection); if(msg == NULL){ sleep(1); continue; } if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){ if(!dbus_message_iter_init(msg, &arg)) fprintf(stderr, "MessageHas no Param"); else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING) fprintf(stderr, "Param isnot string"); else dbus_message_iter_get_basic(&arg, &sigvalue); printf("Got Singal withvalue : %s\n", sigvalue); } dbus_message_unref(msg); }//End of while
}
int main(int argc, char **argv){
listen_signal();
return 0;
}
cmake_minimum_required(VERSION 3.16)
project(dbus_test)
aux_source_directory(. SRCS)
add_executable(test ${SRCS})
target_link_libraries(test dbus-1)
缺少<dbus/dbus.h>
,解决方法:
安装dbus库,若仍未解决,执行下一步
sudo ln -sf /usr/include/dbus-1.0/dbus /usr/include/dbus
,原因:
/usr/include/dbus-1.0
下/usr/include
下查找,上述操作是在/usr/include
创建了所需头文件的软连接缺少dbus-arch-deps.h
,解决方法:
sudo ln -sf /usr/include/dbus-1.0/dbus/dbus-arch-deps.h /usr/include/dbus
,原因同上#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus.h> #include <unistd.h>
void reply_to_method_call(DBusMessage *msg, DBusConnection *conn)
{
DBusMessage *reply;
DBusMessageIter iter;
dbus_uint32_t serial = 0;
int param1, param2;
// 1 读取消息中携带的参数
if(!dbus_message_iter_init(msg, &iter))
{
printf("Message has noargs\n");
return;
}
// 读取第一个参数
if(dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
{
printf("arg1 type error, should intger!\n");
return;
}
else
{
dbus_message_iter_get_basic(&iter, ¶m1);
dbus_message_iter_next(&iter); // 迭代器后移一位
}
// 读取第二个参数
if(dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
{
printf("arg2 type error, should intger!\n");
}
else
{
dbus_message_iter_get_basic(&iter, ¶m2);
}printf("receive method call, param is %d and %d\n", param1, param2); int result = param1 + param2; // 2 创建返回消息reply reply = dbus_message_new_method_return(msg); // 通过消息迭代器在返回消息中填入结果 dbus_message_iter_init_append(reply, &iter); if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &result)){ printf("Out ofMemory!\n"); exit(1); } // 3 发送返回消息 if(!dbus_connection_send(conn, reply, &serial)){ printf("Out of Memory\n"); exit(1); } dbus_connection_flush(conn); dbus_message_unref(reply);
}
void listen_dbus()
{
DBusMessage *msg;
DBusConnection *connection;
DBusError err;// 步骤1 建立连接 dbus_error_init(&err); connection = dbus_bus_get(DBUS_BUS_SESSION, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "ConnectionError %s\n", err.message); dbus_error_free(&err); } if(connection == NULL) return; // 步骤2 设置连接名 int ret = dbus_bus_request_name(connection, "org.example.MethodCallable", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "Name Error %s\n", err.message); dbus_error_free(&err); } while(1) { // 步骤3 循环监听 dbus_connection_read_write(connection, 0); msg = dbus_connection_pop_message(connection); if(msg == NULL){ sleep(1); continue; } // 步骤4 解析调用消息并处理 if(strcmp(dbus_message_get_path(msg), "/org/example/MethodService/Object") == 0){ if(dbus_message_is_method_call(msg, "org.example.MethodService.Add", "AddMethod")){ reply_to_method_call(msg, connection); } } dbus_message_unref(msg); }
}
int main(int argc, char **argv){
listen_dbus();
return 0;
}
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus.h> #include <unistd.h>
DBusConnection* connect_dbus()
{
DBusError err;
DBusConnection *connection;
int ret;// 步骤1 建立连接 dbus_error_init(&err); connection = dbus_bus_get(DBUS_BUS_SESSION, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "ConnectionErr : %s\n", err.message); dbus_error_free(&err); } if(connection == NULL) return NULL; // 步骤2 注册连接名称 ret = dbus_bus_request_name(connection, "org.example.MethodCall", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if(dbus_error_is_set(&err)){ fprintf(stderr, "Name Err :%s\n", err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return NULL; return connection;
}
void send_a_method_call(DBusConnection *connection, int param1, int param2)
{
DBusError err;
DBusMessage *msg;
DBusMessageIter iter;
DBusPendingCall *pending;
int result;// 步骤3 创建调用消息 dbus_error_init(&err); msg = dbus_message_new_method_call("org.example.MethodCallable", "/org/example/MethodService/Object", "org.example.MethodService.Add", "AddMethod"); if(msg == NULL){ fprintf(stderr, "MessageNULL"); return; } // 给定调用参数 dbus_message_iter_init_append(msg, &iter); if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &param1)){ fprintf(stderr, "Out of Memory!"); exit(1); } if(!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &param2)){ fprintf(stderr, "Out of Memory!"); exit(1); } // 步骤4 发送消息,pending用于接收调用后的方法响应 if(!dbus_connection_send_with_reply(connection, msg, &pending, -1)){ fprintf(stderr, "Out of Memory!"); exit(1); } if(pending == NULL){ fprintf(stderr, "Pending CallNULL: connection is disconnected "); dbus_message_unref(msg); return; } dbus_connection_flush(connection); dbus_message_unref(msg); // 步骤5 接收响应 dbus_pending_call_block(pending); // 从响应中拿取数据 msg = dbus_pending_call_steal_reply(pending); if (msg == NULL) { fprintf(stderr, "ReplyNull\n"); exit(1); } dbus_pending_call_unref(pending); // 读取响应数据 if(!dbus_message_iter_init(msg, &iter)) fprintf(stderr, "Message has no ret!\n"); else if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) fprintf(stderr, "Argument is not integer!\n"); else dbus_message_iter_get_basic(&iter, &result); printf("Got Reply: %d\n", result); dbus_message_unref(msg);
}
int main()
{
send_a_method_call(connect_dbus(), 5, 10);ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err); if(dbus_error_is_set(&err)){ fprintf(stderr,"Name Err :%s\n", err.message); dbus_error_free(&err); } if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) return -1;
0
}
reference
g_bus_own_name
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
1
连接到bus_type
指定的总线,并在该总线注册一个连接名称,在总线获取成功时调用bus_acquired_handler
,并分别在名称获取或丢失时调用name_acquired_handler
和name_lost_handler
。
**bus\_type
**
GBusType
G_BUS_TYPE_SESSION
name
const gchar*
well-known
名称flags
GBusNameOwnerFlags
G_BUS_NAME_OWNER_FLAGS_REPLACE| G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
,意为如果另一个消息总线连接拥有该名称并指定了 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
,则从该连接中取走该名称。bus_acquired_handler
类型:
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
2
说明:在连接到类型为bus_type的总线或NULL时调用的处理程序。
name_acquired_handler
类型:
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
3
说明:在名称被获取时调用。
name_lost_handler
类型:
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
4
说明:当名称丢失或连接被关闭时调用。
user_data
gpointer
,实质是void*
NULL
。数据由函数的调用者拥有。user_data_free_func
类型
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
5
说明:指定在销毁数据元素时调用的函数类型。它将指针传递给数据元素,并应释放为此分配的任何内存和资源。参数可以为 NULL
。
guint
g_bus_unown_name()
一起使用的标识符(永远不会是 0),用于停止拥有该名称。g_bus_unown_name
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
6
停止拥有一个名称。
owner_id
g_bus_own_name
的返回值g_signal_connect
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
7
将 GCallback
函数连接到特定对象的信号。这里是这样一种思想:XML文件中定义了Method,客户端调用该Method时,会向服务端发出一个处理该方法的信号。若是服务端使用此函数将信号与一个回调函数连接,就会在收到信号时触发该回调函数。这种handle-method信号由gdbus-codegen
工具根据XML文件中定义的方法自动生成的信号。
详细说明:GObject.signal_connect - GTK 文档。
instance
ExampleAnimal
,是由gdbus-codegen
工具根据XML文件生成的文件中定义的结构体类型。example_animal_skeleton_new()
函数创建的对象实例。标识example_animal_skeleton_new
也是gdbus-codegen
工具根据XML文件生成的函数。example_animal
是根据gdbus-codegen
工具选项和XML文件内容生成的名称,会作为所有生成的函数或是宏的名称的前缀。其中example
是gdbus-codegen
工具选项--c-namespace Example
定义的,animal
则是XML文件中定义的接口名称。detailed_signal
类型:一个标识XML文件中定义的方法的字符串。
具体内容:handle-{methodname}
,其中handle
是固定前缀,methodname
是由XML文件中定义的方法名转换而来的。具体转换方式为从驼峰命名转换成小写且以-
连接。如GetIp → get-ip
。可以在gdbus-codegen
生成的代码中查找信号名,形如
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
8
形式的结构体赋值语句,结构体的原型为
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
9
也就是说,"handle-poke"
就是生成代码为Poke
方法创建的信号。
c_handler
类型:形如
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
0
形式的函数指针。要使用G_CALLBACK
转换该函数指针。
具体说明:相较于生成的头文件中struct _ExampleAnimalIface
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
1
内定义的handle_poke
函数指针,该函数中多了一个gpointer
类型的参数,gpointer
实质是void*
类型,用于传递自定义的一些数据。此处的函数指针名称不作要求,但一般形式都是on_接口名_方法名
。
data
gpointer
g_main_loop_new
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
2
创建一个新的 GMainLoop
结构体。GMainLoop
结构是一个不透明的数据类型,它表示 GLib 或 GTK 应用程序的主事件循环。
context
GMainContext*
。GMainContext
结构体是不透明的数据类型,用于表示要主循环中处理的一组源。NULL
,如果为 NULL
,将使用全局默认的主上下文。数据由函数的调用者持有。is_running
TRUE
以指示循环正在运行。这并不很重要,因为调用 g\_main\_loop\_run()
无论如何都会将其设置为 TRUE
。GMainLoop
GMainLoop
。函数的调用者负责数据的所有权,并负责释放它。g_main_loop_run
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
3
运行主循环,直到在循环上调用 g\_main\_loop\_quit()
。如果这是在循环的 GMainContext
线程上调用,它将处理循环的事件,否则它将只等待。
loop
g_main_loop_new
返回的对象
g_main_loop_unref
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
4
通过一个 GMainLoop
对象的引用次数减一。如果结果是零,则释放循环及其所有相关内存。
g_main_loop_quit
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
5
停止 GMainLoop
的运行。对于此循环的任何 g\_main\_loop\_run()
调用都将返回。
注意,当调用 g\_main\_loop\_quit()
时,已调度的事件源仍将被执行。
g_main_loop_new
创建主事件循环对象g_bus_own_name
创建连接并注册连接名称,且注册回调函数(所有事件都在回调函数中处理)g_main_loop_run
启动主事件循环g_bus_unown_name
停止拥有之前注册的连接名称g_main_loop_unref
释放主事件循环对象资源g_main_loop_new
创建主事件循环对象example_object_manager_client_new_for_bus_sync
同步创建并返回一个对象管理代理客户端(该函数是gdbus-codegen根据XML文件生成的头文件和源文件中包含的函数,并且有异步版本)g_main_loop_run
启动主事件循环创建XML文件,在其中写定接口,接口中包含方法、信号、属性等定义;
使用gdbus-codegen
工具根据XML文件生成代码,包括一个头文件和一个源文件;
引入生成的头文件,利用其中包含的函数和宏等编写代码;
编译运行。
gdbus-example-objectmanager.xml
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
6
<interface name="org.gtk.GDBus.Example.ObjectManager.Animal">
<!-- Mood: The mood of the animal.
@since: 2.30
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
7
</interface>
<!-- org.gtk.GDBus.Example.ObjectManager.Cat:
@short_description: More example docs generated by gdbus-codegen
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
8
<interface name="org.gtk.GDBus.Example.ObjectManager.Cat">
</interface>
</node>
gdbus-example-server.c
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
9
out:
return TRUE;
}
static void
on_bus_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
ExampleObjectSkeleton *object;
guint n;
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
0
}
static void
on_name_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_print("Acquired the name %s\n", name);
}
static void
on_name_lost(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_print("Lost the name %s\n", name);
}
gint main(gint argc, gchar *argv[])
{
GMainLoop *loop;
guint id;
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
1
}
gdbus-example-client.c
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
2
}
static void
on_object_added(GDBusObjectManager *manager,
GDBusObject *object,
gpointer user_data)
{
gchar *owner;
owner = g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager));
g_print("Added object at %s (owner %s)\n", g_dbus_object_get_object_path(object), owner);
g_free(owner);
}
static void
on_object_removed(GDBusObjectManager *manager,
GDBusObject *object,
gpointer user_data)
{
gchar *owner;
owner = g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager));
g_print("Removed object at %s (owner %s)\n", g_dbus_object_get_object_path(object), owner);
g_free(owner);
}
static void
on_notify_name_owner(GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT(object);
gchar *name_owner;
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
3
}
static void
on_interface_proxy_properties_changed(GDBusObjectManagerClient *manager,
GDBusObjectProxy *object_proxy,
GDBusProxy *interface_proxy,
GVariant *changed_properties,
const gchar *const *invalidated_properties,
gpointer user_data)
{
GVariantIter iter;
const gchar *key;
GVariant *value;
gchar *s;
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
4
}
gint main(gint argc, gchar *argv[])
{
GDBusObjectManager *manager;
GMainLoop *loop;
GError *error;
gchar *name_owner;
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
5
out:
// 释放资源
if (manager != NULL)
g_object_unref(manager);
if (loop != NULL)
g_main_loop_unref(loop);
ret = dbus_bus_request_name(connection, "org.example.SignalSource", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr,"Name Err :%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return -1;
0
}
CMakeLists
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
7
首先使用gdbus-codegen
生成代码。
dbus_bool_t dbus_connection_send(
DBusConnection *connection, // D-Bus 连接对象指针
DBusMessage *message, // 待发送的消息对象指针
dbus_uint32_t *serial // 返回消息序列号(可选)
);
8
创建gdbus客户端和服务端程序
创建CMakeLists.txt
创建build
文件夹,进入build
文件夹,cmake ..
,然后make
先执行服务端程序,再执行客户端程序。
gdbus-codegen
生成的代码的介绍生成的代码中包括了绝大多数我们在开发gdbus程序中需要的函数或者别的一些信息。以上文中的XML文件生成的代码举例说明,由于生成的代码文件很大,仅挑选一些片段在此。完整版见gdbus-codegen生成代码1。
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal("/org/example/SignalService/Sender", "org.example.Signal.Test", "Test"))== NULL){
fprintf(stderr, "MessageNULL\n");
return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &arg);
if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue)){
fprintf(stderr, "Out OfMemory!\n");
return -1;
}
// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &serial)){
fprintf(stderr, "Out of Memory!\n");
return -1;
}
dbus_connection_flush(connection);
printf("Signal Send\n");
// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
1
handle_poke
和jumped
信号的回调函数声明,真正的回调函数也只需要在参数列表中增加一个gpointer user_data
参数即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
0
- 上面的几个宏给出了判断对象类型和将对象类型进行转换的方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
1
-
以上代码给出了
- 接口中定义的信号的发送函数
- 接口中定义的方法的同步和异步调用函数,以及调用方完成调用函数
- 接口中定义方法的被调用方完成调用函数
example_animal_complete_poke
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
2
- 以上代码给出了XML文件接口中定义的方法的相关信息,"Poke"是定义的方法名,"handle-poke"是为该方法生成的信号名。
gdbus-codegen生成代码
头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
3
源文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
4
else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
5
endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
6
g_variant_iter_init (&iter, parameters);
while ((child = g_variant_iter_next_value (&iter)) != NULL)
{
_ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
if (arg_info->use_gvariant)
{
g_value_init (¶mv[n], G_TYPE_VARIANT);
g_value_set_variant (¶mv[n], child);
n++;
}
else
g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);
g_variant_unref (child);
}
signal_id = g_signal_lookup (info->signal_name, EXAMPLE_TYPE_ANIMAL);
g_value_init (&return_value, G_TYPE_BOOLEAN);
g_signal_emitv (paramv, signal_id, 0, &return_value);
if (!g_value_get_boolean (&return_value))
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
g_value_unset (&return_value);
for (n = 0; n < num_params + num_extra; n++)
g_value_unset (¶mv[n]);
g_free (paramv);
}
static GVariant *
_example_animal_skeleton_handle_get_property (
GDBusConnection *connection G_GNUC_UNUSED,
const gchar *sender G_GNUC_UNUSED,
const gchar *object_path G_GNUC_UNUSED,
const gchar *interface_name G_GNUC_UNUSED,
const gchar *property_name,
GError **error,
gpointer user_data)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (user_data);
GValue value = G_VALUE_INIT;
GParamSpec *pspec;
_ExtendedGDBusPropertyInfo *info;
GVariant *ret;
ret = NULL;
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_animal_interface_info.parent_struct, property_name);
g_assert (info != NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
if (pspec == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
}
else
{
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
g_value_unset (&value);
}
return ret;
}
static gboolean
_example_animal_skeleton_handle_set_property (
GDBusConnection *connection G_GNUC_UNUSED,
const gchar *sender G_GNUC_UNUSED,
const gchar *object_path G_GNUC_UNUSED,
const gchar *interface_name G_GNUC_UNUSED,
const gchar *property_name,
GVariant *variant,
GError **error,
gpointer user_data)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (user_data);
GValue value = G_VALUE_INIT;
GParamSpec *pspec;
_ExtendedGDBusPropertyInfo *info;
gboolean ret;
ret = FALSE;
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_animal_interface_info.parent_struct, property_name);
g_assert (info != NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
if (pspec == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
}
else
{
if (info->use_gvariant)
g_value_set_variant (&value, variant);
else
g_dbus_gvariant_to_gvalue (variant, &value);
g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
g_value_unset (&value);
ret = TRUE;
}
return ret;
}
static const GDBusInterfaceVTable _example_animal_skeleton_vtable =
{
_example_animal_skeleton_handle_method_call,
_example_animal_skeleton_handle_get_property,
_example_animal_skeleton_handle_set_property,
{NULL}
};
static GDBusInterfaceInfo *
example_animal_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
{
return example_animal_interface_info ();
}
static GDBusInterfaceVTable *
example_animal_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
{
return (GDBusInterfaceVTable *) &_example_animal_skeleton_vtable;
}
static GVariant *
example_animal_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (_skeleton);
GVariantBuilder builder;
guint n;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
if (_example_animal_interface_info.parent_struct.properties == NULL)
goto out;
for (n = 0; _example_animal_interface_info.parent_struct.properties[n] != NULL; n++)
{
GDBusPropertyInfo *info = _example_animal_interface_info.parent_struct.properties[n];
if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
{
GVariant *value;
value = _example_animal_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.gtk.GDBus.Example.ObjectManager.Animal", info->name, NULL, skeleton);
if (value != NULL)
{
g_variant_take_ref (value);
g_variant_builder_add (&builder, "{sv}", info->name, value);
g_variant_unref (value);
}
}
}
out:
return g_variant_builder_end (&builder);
}
static gboolean _example_animal_emit_changed (gpointer user_data);
static void
example_animal_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (_skeleton);
gboolean emit_changed = FALSE;
g_mutex_lock (&skeleton->priv->lock);
if (skeleton->priv->changed_properties_idle_source != NULL)
{
g_source_destroy (skeleton->priv->changed_properties_idle_source);
skeleton->priv->changed_properties_idle_source = NULL;
emit_changed = TRUE;
}
g_mutex_unlock (&skeleton->priv->lock);
if (emit_changed)
_example_animal_emit_changed (skeleton);
}
static void
_example_animal_on_signal_jumped (
ExampleAnimal *object,
gdouble arg_height)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
GList *connections, *l;
GVariant *signal_variant;
connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
signal_variant = g_variant_ref_sink (g_variant_new ("(d)",
arg_height));
for (l = connections; l != NULL; l = l->next)
{
GDBusConnection *connection = l->data;
g_dbus_connection_emit_signal (connection,
NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.gtk.GDBus.Example.ObjectManager.Animal", "Jumped",
signal_variant, NULL);
}
g_variant_unref (signal_variant);
g_list_free_full (connections, g_object_unref);
}
static void example_animal_skeleton_iface_init (ExampleAnimalIface *iface);
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
G_DEFINE_TYPE_WITH_CODE (ExampleAnimalSkeleton, example_animal_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
G_ADD_PRIVATE (ExampleAnimalSkeleton)
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_ANIMAL, example_animal_skeleton_iface_init))
else
G_DEFINE_TYPE_WITH_CODE (ExampleAnimalSkeleton, example_animal_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_ANIMAL, example_animal_skeleton_iface_init))
endif
static void
example_animal_skeleton_finalize (GObject *object)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
guint n;
for (n = 0; n < 3; n++)
g_value_unset (&skeleton->priv->properties[n]);
g_free (skeleton->priv->properties);
g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
if (skeleton->priv->changed_properties_idle_source != NULL)
g_source_destroy (skeleton->priv->changed_properties_idle_source);
g_main_context_unref (skeleton->priv->context);
g_mutex_clear (&skeleton->priv->lock);
G_OBJECT_CLASS (example_animal_skeleton_parent_class)->finalize (object);
}
static void
example_animal_skeleton_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec G_GNUC_UNUSED)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
g_assert (prop_id != 0 && prop_id - 1 < 3);
g_mutex_lock (&skeleton->priv->lock);
g_value_copy (&skeleton->priv->properties[prop_id - 1], value);
g_mutex_unlock (&skeleton->priv->lock);
}
static gboolean
_example_animal_emit_changed (gpointer user_data)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (user_data);
GList *l;
GVariantBuilder builder;
GVariantBuilder invalidated_builder;
guint num_changes;
g_mutex_lock (&skeleton->priv->lock);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
for (l = skeleton->priv->changed_properties, num_changes = 0; l != NULL; l = l->next)
{
ChangedProperty *cp = l->data;
GVariant *variant;
const GValue *cur_value;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
7
if (num_changes > 0)
{
GList *connections, *ll;
GVariant *signal_variant;
signal_variant = g_variant_ref_sink (g_variant_new ("(sa{sv}as)", "org.gtk.GDBus.Example.ObjectManager.Animal",
&builder, &invalidated_builder));
connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
for (ll = connections; ll != NULL; ll = ll->next)
{
GDBusConnection *connection = ll->data;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
8
else
{
g_variant_builder_clear (&builder);
g_variant_builder_clear (&invalidated_builder);
}
g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
skeleton->priv->changed_properties = NULL;
skeleton->priv->changed_properties_idle_source = NULL;
g_mutex_unlock (&skeleton->priv->lock);
return FALSE;
}
static void
_example_animal_schedule_emit_changed (ExampleAnimalSkeleton *skeleton, const _ExtendedGDBusPropertyInfo *info, guint prop_id, const GValue *orig_value)
{
ChangedProperty *cp;
GList *l;
cp = NULL;
for (l = skeleton->priv->changed_properties; l != NULL; l = l->next)
{
ChangedProperty *i_cp = l->data;
if (i_cp->info == info)
{
cp = i_cp;
break;
}
}
if (cp == NULL)
{
cp = g_new0 (ChangedProperty, 1);
cp->prop_id = prop_id;
cp->info = info;
skeleton->priv->changed_properties = g_list_prepend (skeleton->priv->changed_properties, cp);
g_value_init (&cp->orig_value, G_VALUE_TYPE (orig_value));
g_value_copy (orig_value, &cp->orig_value);
}
}
static void
example_animal_skeleton_notify (GObject *object,
GParamSpec *pspec G_GNUC_UNUSED)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
g_mutex_lock (&skeleton->priv->lock);
if (skeleton->priv->changed_properties != NULL &&
skeleton->priv->changed_properties_idle_source == NULL)
{
skeleton->priv->changed_properties_idle_source = g_idle_source_new ();
g_source_set_priority (skeleton->priv->changed_properties_idle_source, G_PRIORITY_DEFAULT);
g_source_set_callback (skeleton->priv->changed_properties_idle_source, _example_animal_emit_changed, g_object_ref (skeleton), (GDestroyNotify) g_object_unref);
g_source_set_name (skeleton->priv->changed_properties_idle_source, "[generated] _example_animal_emit_changed");
g_source_attach (skeleton->priv->changed_properties_idle_source, skeleton->priv->context);
g_source_unref (skeleton->priv->changed_properties_idle_source);
}
g_mutex_unlock (&skeleton->priv->lock);
}
static void
example_animal_skeleton_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
const _ExtendedGDBusPropertyInfo *info;
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
g_assert (prop_id != 0 && prop_id - 1 < 3);
info = (const _ExtendedGDBusPropertyInfo *) _example_animal_property_info_pointers[prop_id - 1];
g_mutex_lock (&skeleton->priv->lock);
g_object_freeze_notify (object);
if (!_g_value_equal (value, &skeleton->priv->properties[prop_id - 1]))
{
if (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)) != NULL &&
info->emits_changed_signal)
_example_animal_schedule_emit_changed (skeleton, info, prop_id, &skeleton->priv->properties[prop_id - 1]);
g_value_copy (value, &skeleton->priv->properties[prop_id - 1]);
g_object_notify_by_pspec (object, pspec);
}
g_mutex_unlock (&skeleton->priv->lock);
g_object_thaw_notify (object);
}
static void
example_animal_skeleton_init (ExampleAnimalSkeleton *skeleton)
{
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
skeleton->priv = example_animal_skeleton_get_instance_private (skeleton);
else
skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, EXAMPLE_TYPE_ANIMAL_SKELETON, ExampleAnimalSkeletonPrivate);
endif
g_mutex_init (&skeleton->priv->lock);
skeleton->priv->context = g_main_context_ref_thread_default ();
skeleton->priv->properties = g_new0 (GValue, 3);
g_value_init (&skeleton->priv->properties[0], G_TYPE_STRING);
g_value_init (&skeleton->priv->properties[1], G_TYPE_STRING);
g_value_init (&skeleton->priv->properties[2], G_TYPE_STRING);
}
static const gchar *
example_animal_skeleton_get_mood (ExampleAnimal *object)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
const gchar *value;
g_mutex_lock (&skeleton->priv->lock);
value = g_value_get_string (&(skeleton->priv->properties[0]));
g_mutex_unlock (&skeleton->priv->lock);
return value;
}
static const gchar *
example_animal_skeleton_get_foo (ExampleAnimal *object)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
const gchar *value;
g_mutex_lock (&skeleton->priv->lock);
value = g_value_get_string (&(skeleton->priv->properties[1]));
g_mutex_unlock (&skeleton->priv->lock);
return value;
}
static const gchar *
example_animal_skeleton_get_bar (ExampleAnimal *object)
{
ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_SKELETON (object);
const gchar *value;
g_mutex_lock (&skeleton->priv->lock);
value = g_value_get_string (&(skeleton->priv->properties[2]));
g_mutex_unlock (&skeleton->priv->lock);
return value;
}
static void
example_animal_skeleton_class_init (ExampleAnimalSkeletonClass *klass)
{
GObjectClass *gobject_class;
GDBusInterfaceSkeletonClass *skeleton_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = example_animal_skeleton_finalize;
gobject_class->get_property = example_animal_skeleton_get_property;
gobject_class->set_property = example_animal_skeleton_set_property;
gobject_class->notify = example_animal_skeleton_notify;
example_animal_override_properties (gobject_class, 1);
skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
skeleton_class->get_info = example_animal_skeleton_dbus_interface_get_info;
skeleton_class->get_properties = example_animal_skeleton_dbus_interface_get_properties;
skeleton_class->flush = example_animal_skeleton_dbus_interface_flush;
skeleton_class->get_vtable = example_animal_skeleton_dbus_interface_get_vtable;
if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
g_type_class_add_private (klass, sizeof (ExampleAnimalSkeletonPrivate));
endif
}
static void
example_animal_skeleton_iface_init (ExampleAnimalIface *iface)
{
iface->jumped = _example_animal_on_signal_jumped;
iface->get_mood = example_animal_skeleton_get_mood;
iface->get_foo = example_animal_skeleton_get_foo;
iface->get_bar = example_animal_skeleton_get_bar;
}
/**
- example_animal_skeleton_new:
- Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link>.
- Returns: (transfer full) (type ExampleAnimalSkeleton): The skeleton object.
- Since: 2.30
*/
ExampleAnimal *
example_animal_skeleton_new (void)
{
return EXAMPLE_ANIMAL (g_object_new (EXAMPLE_TYPE_ANIMAL_SKELETON, NULL));
}
/* ------------------------------------------------------------------------
- Code for interface org.gtk.GDBus.Example.ObjectManager.Cat
-
*/
/**
- SECTION:ExampleCat
- @title: ExampleCat
- @short_description: Generated C code for the org.gtk.GDBus.Example.ObjectManager.Cat D-Bus interface
- This section contains code for working with the <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link> D-Bus interface in C.
*/
/* ---- Introspection data for org.gtk.GDBus.Example.ObjectManager.Cat ---- */
static const _ExtendedGDBusInterfaceInfo _example_cat_interface_info =
{
{
-1,
(gchar *) "org.gtk.GDBus.Example.ObjectManager.Cat",
NULL,
NULL,
NULL,
NULL
},
"cat",
};
/**
- example_cat_interface_info:
- Gets a machine-readable description of the <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link> D-Bus interface.
- Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
*/
GDBusInterfaceInfo *
example_cat_interface_info (void)
{
return (GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct;
}
/**
- example_cat_override_properties:
- @klass: The class structure for a #GObject derived class.
- @property_id_begin: The property id to assign to the first overridden property.
- Overrides all #GObject properties in the #ExampleCat interface for a concrete class.
- The properties are overridden in the order they are defined.
- Returns: The last property id.
*/
guint
example_cat_override_properties (GObjectClass *klass, guint property_id_begin)
{
return property_id_begin - 1;
}
/**
- ExampleCat:
- Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>.
*/
/**
- ExampleCatIface:
- @parent_iface: The parent interface.
- Virtual table for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>.
*/
typedef ExampleCatIface ExampleCatInterface;
G_DEFINE_INTERFACE (ExampleCat, example_cat, G_TYPE_OBJECT)
static void
example_cat_default_init (ExampleCatIface *iface)
{
}
/* ------------------------------------------------------------------------ */
/**
- ExampleCatProxy:
- The #ExampleCatProxy structure contains only private data and should only be accessed using the provided API.
*/
/**
- ExampleCatProxyClass:
- @parent_class: The parent class.
- Class structure for #ExampleCatProxy.
*/
struct _ExampleCatProxyPrivate
{
GData *qdata;
};
static void example_cat_proxy_iface_init (ExampleCatIface *iface);
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
G_DEFINE_TYPE_WITH_CODE (ExampleCatProxy, example_cat_proxy, G_TYPE_DBUS_PROXY,
G_ADD_PRIVATE (ExampleCatProxy)
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_CAT, example_cat_proxy_iface_init))
else
G_DEFINE_TYPE_WITH_CODE (ExampleCatProxy, example_cat_proxy, G_TYPE_DBUS_PROXY,
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_CAT, example_cat_proxy_iface_init))
endif
static void
example_cat_proxy_finalize (GObject *object)
{
ExampleCatProxy *proxy = EXAMPLE_CAT_PROXY (object);
g_datalist_clear (&proxy->priv->qdata);
G_OBJECT_CLASS (example_cat_proxy_parent_class)->finalize (object);
}
static void
example_cat_proxy_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec G_GNUC_UNUSED)
{
}
static void
example_cat_proxy_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec G_GNUC_UNUSED)
{
}
static void
example_cat_proxy_g_signal (GDBusProxy *proxy,
const gchar *sender_name G_GNUC_UNUSED,
const gchar *signal_name,
GVariant *parameters)
{
_ExtendedGDBusSignalInfo *info;
GVariantIter iter;
GVariant *child;
GValue *paramv;
gsize num_params;
gsize n;
guint signal_id;
info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct, signal_name);
if (info == NULL)
return;
num_params = g_variant_n_children (parameters);
paramv = g_new0 (GValue, num_params + 1);
g_value_init (¶mv[0], EXAMPLE_TYPE_CAT);
g_value_set_object (¶mv[0], proxy);
g_variant_iter_init (&iter, parameters);
n = 1;
while ((child = g_variant_iter_next_value (&iter)) != NULL)
{
_ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
if (arg_info->use_gvariant)
{
g_value_init (¶mv[n], G_TYPE_VARIANT);
g_value_set_variant (¶mv[n], child);
n++;
}
else
g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);
g_variant_unref (child);
}
signal_id = g_signal_lookup (info->signal_name, EXAMPLE_TYPE_CAT);
g_signal_emitv (paramv, signal_id, 0, NULL);
for (n = 0; n < num_params + 1; n++)
g_value_unset (¶mv[n]);
g_free (paramv);
}
static void
example_cat_proxy_g_properties_changed (GDBusProxy *_proxy,
GVariant *changed_properties,
const gchar *const *invalidated_properties)
{
ExampleCatProxy *proxy = EXAMPLE_CAT_PROXY (_proxy);
guint n;
const gchar *key;
GVariantIter *iter;
_ExtendedGDBusPropertyInfo *info;
g_variant_get (changed_properties, "a{sv}", &iter);
while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
{
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct, key);
g_datalist_remove_data (&proxy->priv->qdata, key);
if (info != NULL)
g_object_notify (G_OBJECT (proxy), info->hyphen_name);
}
g_variant_iter_free (iter);
for (n = 0; invalidated_properties[n] != NULL; n++)
{
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct, invalidated_properties[n]);
g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
if (info != NULL)
g_object_notify (G_OBJECT (proxy), info->hyphen_name);
}
}
static void
example_cat_proxy_init (ExampleCatProxy *proxy)
{
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
proxy->priv = example_cat_proxy_get_instance_private (proxy);
else
proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, EXAMPLE_TYPE_CAT_PROXY, ExampleCatProxyPrivate);
endif
g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), example_cat_interface_info ());
}
static void
example_cat_proxy_class_init (ExampleCatProxyClass *klass)
{
GObjectClass *gobject_class;
GDBusProxyClass *proxy_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = example_cat_proxy_finalize;
gobject_class->get_property = example_cat_proxy_get_property;
gobject_class->set_property = example_cat_proxy_set_property;
proxy_class = G_DBUS_PROXY_CLASS (klass);
proxy_class->g_signal = example_cat_proxy_g_signal;
proxy_class->g_properties_changed = example_cat_proxy_g_properties_changed;
if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
g_type_class_add_private (klass, sizeof (ExampleCatProxyPrivate));
endif
}
static void
example_cat_proxy_iface_init (ExampleCatIface *iface)
{
}
/**
- example_cat_proxy_new:
- @connection: A #GDBusConnection.
- @flags: Flags from the #GDBusProxyFlags enumeration.
- @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @callback: A #GAsyncReadyCallback to call when the request is satisfied.
- @user_data: User data to pass to @callback.
- Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>. See g_dbus_proxy_new() for more details.
- When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).
- You can then call example_cat_proxy_new_finish() to get the result of the operation.
- See example_cat_proxy_new_sync() for the synchronous, blocking version of this constructor.
*/
void
example_cat_proxy_new (
GDBusConnection *connection,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_async_initable_new_async (EXAMPLE_TYPE_CAT_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.gtk.GDBus.Example.ObjectManager.Cat", NULL);
}
/**
- example_cat_proxy_new_finish:
- @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_cat_proxy_new().
- @error: Return location for error or %NULL
- Finishes an operation started with example_cat_proxy_new().
- Returns: (transfer full) (type ExampleCatProxy): The constructed proxy object or %NULL if @error is set.
*/
ExampleCat *
example_cat_proxy_new_finish (
GAsyncResult *res,
GError **error)
{
GObject *ret;
GObject *source_object;
source_object = g_async_result_get_source_object (res);
ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
g_object_unref (source_object);
if (ret != NULL)
return EXAMPLE_CAT (ret);
else
return NULL;
}
/**
- example_cat_proxy_new_sync:
- @connection: A #GDBusConnection.
- @flags: Flags from the #GDBusProxyFlags enumeration.
- @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @error: Return location for error or %NULL
- Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>. See g_dbus_proxy_new_sync() for more details.
- The calling thread is blocked until a reply is received.
- See example_cat_proxy_new() for the asynchronous version of this constructor.
- Returns: (transfer full) (type ExampleCatProxy): The constructed proxy object or %NULL if @error is set.
*/
ExampleCat *
example_cat_proxy_new_sync (
GDBusConnection *connection,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error)
{
GInitable *ret;
ret = g_initable_new (EXAMPLE_TYPE_CAT_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "org.gtk.GDBus.Example.ObjectManager.Cat", NULL);
if (ret != NULL)
return EXAMPLE_CAT (ret);
else
return NULL;
}
/**
- example_cat_proxy_new_for_bus:
- @bus_type: A #GBusType.
- @flags: Flags from the #GDBusProxyFlags enumeration.
- @name: A bus name (well-known or unique).
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @callback: A #GAsyncReadyCallback to call when the request is satisfied.
- @user_data: User data to pass to @callback.
- Like example_cat_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
- When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).
- You can then call example_cat_proxy_new_for_bus_finish() to get the result of the operation.
- See example_cat_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
*/
void
example_cat_proxy_new_for_bus (
GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_async_initable_new_async (EXAMPLE_TYPE_CAT_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.gtk.GDBus.Example.ObjectManager.Cat", NULL);
}
/**
- example_cat_proxy_new_for_bus_finish:
- @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_cat_proxy_new_for_bus().
- @error: Return location for error or %NULL
- Finishes an operation started with example_cat_proxy_new_for_bus().
- Returns: (transfer full) (type ExampleCatProxy): The constructed proxy object or %NULL if @error is set.
*/
ExampleCat *
example_cat_proxy_new_for_bus_finish (
GAsyncResult *res,
GError **error)
{
GObject *ret;
GObject *source_object;
source_object = g_async_result_get_source_object (res);
ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
g_object_unref (source_object);
if (ret != NULL)
return EXAMPLE_CAT (ret);
else
return NULL;
}
/**
- example_cat_proxy_new_for_bus_sync:
- @bus_type: A #GBusType.
- @flags: Flags from the #GDBusProxyFlags enumeration.
- @name: A bus name (well-known or unique).
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @error: Return location for error or %NULL
- Like example_cat_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
- The calling thread is blocked until a reply is received.
- See example_cat_proxy_new_for_bus() for the asynchronous version of this constructor.
- Returns: (transfer full) (type ExampleCatProxy): The constructed proxy object or %NULL if @error is set.
*/
ExampleCat *
example_cat_proxy_new_for_bus_sync (
GBusType bus_type,
GDBusProxyFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error)
{
GInitable *ret;
ret = g_initable_new (EXAMPLE_TYPE_CAT_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "org.gtk.GDBus.Example.ObjectManager.Cat", NULL);
if (ret != NULL)
return EXAMPLE_CAT (ret);
else
return NULL;
}
/* ------------------------------------------------------------------------ */
/**
- ExampleCatSkeleton:
- The #ExampleCatSkeleton structure contains only private data and should only be accessed using the provided API.
*/
/**
- ExampleCatSkeletonClass:
- @parent_class: The parent class.
- Class structure for #ExampleCatSkeleton.
*/
struct _ExampleCatSkeletonPrivate
{
GValue *properties;
GList *changed_properties;
GSource *changed_properties_idle_source;
GMainContext *context;
GMutex lock;
};
static void
_example_cat_skeleton_handle_method_call (
GDBusConnection *connection G_GNUC_UNUSED,
const gchar *sender G_GNUC_UNUSED,
const gchar *object_path G_GNUC_UNUSED,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
ExampleCatSkeleton *skeleton = EXAMPLE_CAT_SKELETON (user_data);
_ExtendedGDBusMethodInfo *info;
GVariantIter iter;
GVariant *child;
GValue *paramv;
gsize num_params;
guint num_extra;
gsize n;
guint signal_id;
GValue return_value = G_VALUE_INIT;
info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
g_assert (info != NULL);
num_params = g_variant_n_children (parameters);
num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
n = 0;
g_value_init (¶mv[n], EXAMPLE_TYPE_CAT);
g_value_set_object (¶mv[n++], skeleton);
g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION);
g_value_set_object (¶mv[n++], invocation);
if (info->pass_fdlist)
{
ifdef G_OS_UNIX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
9
else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
5
endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include <unistd.h>
void listen_signal()
{
// 创建所需变量
DBusMessage *msg;
DBusMessageIter arg;
DBusConnection *connection;
DBusError err;
int ret;
char * sigvalue;
// 步骤1:建立与session bus的连接
dbus_error_init(&err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "ConnectionError %s\n", err.message);
dbus_error_free(&err);
}
if(connection == NULL)
return;
// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, "org.example.SignalReceiver", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if(dbus_error_is_set(&err)){
fprintf(stderr, "Name Error%s\n", err.message);
dbus_error_free(&err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;
// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, "type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'", &err);
dbus_connection_flush(connection); // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&err)){
fprintf(stderr, "Match Error%s\n", err.message);
dbus_error_free(&err);
}
// 步骤4:在循环中监听,每隔开1秒,就去试图自己的连接中获取这个信号。这里给出的是从连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。我们也可以通过这个方式来获取method call消息。
while(1){
dbus_connection_read_write(connection, 0); // 非阻塞读写
msg = dbus_connection_pop_message(connection);
if(msg == NULL){
sleep(1);
continue;
}
if(dbus_message_is_signal(msg, "org.example.Signal.Test", "Test")){
if(!dbus_message_iter_init(msg, &arg))
fprintf(stderr, "MessageHas no Param");
else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
fprintf(stderr, "Param isnot string");
else
dbus_message_iter_get_basic(&arg, &sigvalue);
printf("Got Singal withvalue : %s\n", sigvalue);
}
dbus_message_unref(msg);
}//End of while
6
g_variant_iter_init (&iter, parameters);
while ((child = g_variant_iter_next_value (&iter)) != NULL)
{
_ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
if (arg_info->use_gvariant)
{
g_value_init (¶mv[n], G_TYPE_VARIANT);
g_value_set_variant (¶mv[n], child);
n++;
}
else
g_dbus_gvariant_to_gvalue (child, ¶mv[n++]);
g_variant_unref (child);
}
signal_id = g_signal_lookup (info->signal_name, EXAMPLE_TYPE_CAT);
g_value_init (&return_value, G_TYPE_BOOLEAN);
g_signal_emitv (paramv, signal_id, 0, &return_value);
if (!g_value_get_boolean (&return_value))
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
g_value_unset (&return_value);
for (n = 0; n < num_params + num_extra; n++)
g_value_unset (¶mv[n]);
g_free (paramv);
}
static GVariant *
_example_cat_skeleton_handle_get_property (
GDBusConnection *connection G_GNUC_UNUSED,
const gchar *sender G_GNUC_UNUSED,
const gchar *object_path G_GNUC_UNUSED,
const gchar *interface_name G_GNUC_UNUSED,
const gchar *property_name,
GError **error,
gpointer user_data)
{
ExampleCatSkeleton *skeleton = EXAMPLE_CAT_SKELETON (user_data);
GValue value = G_VALUE_INIT;
GParamSpec *pspec;
_ExtendedGDBusPropertyInfo *info;
GVariant *ret;
ret = NULL;
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct, property_name);
g_assert (info != NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
if (pspec == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
}
else
{
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
g_value_unset (&value);
}
return ret;
}
static gboolean
_example_cat_skeleton_handle_set_property (
GDBusConnection *connection G_GNUC_UNUSED,
const gchar *sender G_GNUC_UNUSED,
const gchar *object_path G_GNUC_UNUSED,
const gchar *interface_name G_GNUC_UNUSED,
const gchar *property_name,
GVariant *variant,
GError **error,
gpointer user_data)
{
ExampleCatSkeleton *skeleton = EXAMPLE_CAT_SKELETON (user_data);
GValue value = G_VALUE_INIT;
GParamSpec *pspec;
_ExtendedGDBusPropertyInfo *info;
gboolean ret;
ret = FALSE;
info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_example_cat_interface_info.parent_struct, property_name);
g_assert (info != NULL);
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
if (pspec == NULL)
{
g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
}
else
{
if (info->use_gvariant)
g_value_set_variant (&value, variant);
else
g_dbus_gvariant_to_gvalue (variant, &value);
g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
g_value_unset (&value);
ret = TRUE;
}
return ret;
}
static const GDBusInterfaceVTable _example_cat_skeleton_vtable =
{
_example_cat_skeleton_handle_method_call,
_example_cat_skeleton_handle_get_property,
_example_cat_skeleton_handle_set_property,
{NULL}
};
static GDBusInterfaceInfo *
example_cat_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
{
return example_cat_interface_info ();
}
static GDBusInterfaceVTable *
example_cat_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton G_GNUC_UNUSED)
{
return (GDBusInterfaceVTable *) &_example_cat_skeleton_vtable;
}
static GVariant *
example_cat_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
{
ExampleCatSkeleton *skeleton = EXAMPLE_CAT_SKELETON (_skeleton);
GVariantBuilder builder;
guint n;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
if (_example_cat_interface_info.parent_struct.properties == NULL)
goto out;
for (n = 0; _example_cat_interface_info.parent_struct.properties[n] != NULL; n++)
{
GDBusPropertyInfo *info = _example_cat_interface_info.parent_struct.properties[n];
if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
{
GVariant *value;
value = _example_cat_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "org.gtk.GDBus.Example.ObjectManager.Cat", info->name, NULL, skeleton);
if (value != NULL)
{
g_variant_take_ref (value);
g_variant_builder_add (&builder, "{sv}", info->name, value);
g_variant_unref (value);
}
}
}
out:
return g_variant_builder_end (&builder);
}
static void
example_cat_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
{
}
static void example_cat_skeleton_iface_init (ExampleCatIface *iface);
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
G_DEFINE_TYPE_WITH_CODE (ExampleCatSkeleton, example_cat_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
G_ADD_PRIVATE (ExampleCatSkeleton)
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_CAT, example_cat_skeleton_iface_init))
else
G_DEFINE_TYPE_WITH_CODE (ExampleCatSkeleton, example_cat_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_CAT, example_cat_skeleton_iface_init))
endif
static void
example_cat_skeleton_finalize (GObject *object)
{
ExampleCatSkeleton *skeleton = EXAMPLE_CAT_SKELETON (object);
g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
if (skeleton->priv->changed_properties_idle_source != NULL)
g_source_destroy (skeleton->priv->changed_properties_idle_source);
g_main_context_unref (skeleton->priv->context);
g_mutex_clear (&skeleton->priv->lock);
G_OBJECT_CLASS (example_cat_skeleton_parent_class)->finalize (object);
}
static void
example_cat_skeleton_init (ExampleCatSkeleton *skeleton)
{
if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38
skeleton->priv = example_cat_skeleton_get_instance_private (skeleton);
else
skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, EXAMPLE_TYPE_CAT_SKELETON, ExampleCatSkeletonPrivate);
endif
g_mutex_init (&skeleton->priv->lock);
skeleton->priv->context = g_main_context_ref_thread_default ();
}
static void
example_cat_skeleton_class_init (ExampleCatSkeletonClass *klass)
{
GObjectClass *gobject_class;
GDBusInterfaceSkeletonClass *skeleton_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = example_cat_skeleton_finalize;
skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
skeleton_class->get_info = example_cat_skeleton_dbus_interface_get_info;
skeleton_class->get_properties = example_cat_skeleton_dbus_interface_get_properties;
skeleton_class->flush = example_cat_skeleton_dbus_interface_flush;
skeleton_class->get_vtable = example_cat_skeleton_dbus_interface_get_vtable;
if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38
g_type_class_add_private (klass, sizeof (ExampleCatSkeletonPrivate));
endif
}
static void
example_cat_skeleton_iface_init (ExampleCatIface *iface)
{
}
/**
- example_cat_skeleton_new:
- Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>.
- Returns: (transfer full) (type ExampleCatSkeleton): The skeleton object.
*/
ExampleCat *
example_cat_skeleton_new (void)
{
return EXAMPLE_CAT (g_object_new (EXAMPLE_TYPE_CAT_SKELETON, NULL));
}
/* ------------------------------------------------------------------------
- Code for Object, ObjectProxy and ObjectSkeleton
-
*/
/**
- SECTION:ExampleObject
- @title: ExampleObject
- @short_description: Specialized GDBusObject types
- This section contains the #ExampleObject, #ExampleObjectProxy, and #ExampleObjectSkeleton types which make it easier to work with objects implementing generated types for D-Bus interfaces.
*/
/**
- ExampleObject:
- The #ExampleObject type is a specialized container of interfaces.
*/
/**
- ExampleObjectIface:
- @parent_iface: The parent interface.
- Virtual table for the #ExampleObject interface.
*/
typedef ExampleObjectIface ExampleObjectInterface;
G_DEFINE_INTERFACE_WITH_CODE (ExampleObject, example_object, G_TYPE_OBJECT, g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_DBUS_OBJECT)
static void
example_object_default_init (ExampleObjectIface iface)
{
/*
- ExampleObject:animal:
- The #ExampleAnimal instance corresponding to the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link>, if any.
- Connect to the #GObject::notify signal to get informed of property changes.
- Since: 2.30
*/
g_object_interface_install_property (iface, g_param_spec_object ("animal", "animal", "animal", EXAMPLE_TYPE_ANIMAL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
- ExampleObject
- The #ExampleCat instance corresponding to the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link>, if any.
- Connect to the #GObject::notify signal to get informed of property changes.
*/
g_object_interface_install_property (iface, g_param_spec_object ("cat", "cat", "cat", EXAMPLE_TYPE_CAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
/**
- example_object_get_animal:
- @object: A #ExampleObject.
- Gets the #ExampleAnimal instance for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link> on @object, if any.
- Returns: (transfer full) (nullable): A #ExampleAnimal that must be freed with g_object_unref() or %NULL if @object does not implement the interface.
- Since: 2.30
*/
ExampleAnimal *example_object_get_animal (ExampleObject *object)
{
GDBusInterface *ret;
ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Animal");
if (ret == NULL)
return NULL;
return EXAMPLE_ANIMAL (ret);
}
/**
- example_object_get_cat:
- @object: A #ExampleObject.
- Gets the #ExampleCat instance for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link> on @object, if any.
- Returns: (transfer full) (nullable): A #ExampleCat that must be freed with g_object_unref() or %NULL if @object does not implement the interface.
*/
ExampleCat *example_object_get_cat (ExampleObject *object)
{
GDBusInterface *ret;
ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Cat");
if (ret == NULL)
return NULL;
return EXAMPLE_CAT (ret);
}
/**
- example_object_peek_animal: (skip)
- @object: A #ExampleObject.
- Like example_object_get_animal() but doesn't increase the reference count on the returned object.
- It is not safe to use the returned object if you are on another thread than the one where the #GDBusObjectManagerClient or #GDBusObjectManagerServer for @object is running.
- Returns: (transfer none) (nullable): A #ExampleAnimal or %NULL if @object does not implement the interface. Do not free the returned object, it is owned by @object.
- Since: 2.30
*/
ExampleAnimal *example_object_peek_animal (ExampleObject *object)
{
GDBusInterface *ret;
ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Animal");
if (ret == NULL)
return NULL;
g_object_unref (ret);
return EXAMPLE_ANIMAL (ret);
}
/**
- example_object_peek_cat: (skip)
- @object: A #ExampleObject.
- Like example_object_get_cat() but doesn't increase the reference count on the returned object.
- It is not safe to use the returned object if you are on another thread than the one where the #GDBusObjectManagerClient or #GDBusObjectManagerServer for @object is running.
- Returns: (transfer none) (nullable): A #ExampleCat or %NULL if @object does not implement the interface. Do not free the returned object, it is owned by @object.
*/
ExampleCat *example_object_peek_cat (ExampleObject *object)
{
GDBusInterface *ret;
ret = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Cat");
if (ret == NULL)
return NULL;
g_object_unref (ret);
return EXAMPLE_CAT (ret);
}
static void
example_object_notify (GDBusObject *object, GDBusInterface *interface)
{
_ExtendedGDBusInterfaceInfo *info = (_ExtendedGDBusInterfaceInfo ) g_dbus_interface_get_info (interface);
/ info can be NULL if the other end is using a D-Bus interface we don't know
- anything about, for example old generated code in this process talking to
- newer generated code in the other process. */
if (info != NULL)
g_object_notify (G_OBJECT (object), info->hyphen_name);
}
/**
- ExampleObjectProxy:
- The #ExampleObjectProxy structure contains only private data and should only be accessed using the provided API.
*/
/**
- ExampleObjectProxyClass:
- @parent_class: The parent class.
- Class structure for #ExampleObjectProxy.
*/
static void
example_object_proxy__example_object_iface_init (ExampleObjectIface *iface G_GNUC_UNUSED)
{
}
static void
example_object_proxy__g_dbus_object_iface_init (GDBusObjectIface *iface)
{
iface->interface_added = example_object_notify;
iface->interface_removed = example_object_notify;
}
G_DEFINE_TYPE_WITH_CODE (ExampleObjectProxy, example_object_proxy, G_TYPE_DBUS_OBJECT_PROXY,
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_OBJECT, example_object_proxy__example_object_iface_init)
G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, example_object_proxy__g_dbus_object_iface_init))
static void
example_object_proxy_init (ExampleObjectProxy *object G_GNUC_UNUSED)
{
}
static void
example_object_proxy_set_property (GObject *gobject,
guint prop_id,
const GValue *value G_GNUC_UNUSED,
GParamSpec *pspec)
{
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
static void
example_object_proxy_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ExampleObjectProxy *object = EXAMPLE_OBJECT_PROXY (gobject);
GDBusInterface *interface;
switch (prop_id)
{
case 1:
interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Animal");
g_value_take_object (value, interface);
break;
cmake_minimum_required(VERSION 3.16)
project(dbus_test)
aux_source_directory(. SRCS)
add_executable(test ${SRCS})
target_link_libraries(test dbus-1)
2
}
}
static void
example_object_proxy_class_init (ExampleObjectProxyClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = example_object_proxy_set_property;
gobject_class->get_property = example_object_proxy_get_property;
g_object_class_override_property (gobject_class, 1, "animal");
g_object_class_override_property (gobject_class, 2, "cat");
}
/**
- example_object_proxy_new:
- @connection: A #GDBusConnection.
- @object_path: An object path.
- Creates a new proxy object.
- Returns: (transfer full): The proxy object.
*/
ExampleObjectProxy *
example_object_proxy_new (GDBusConnection *connection,
const gchar *object_path)
{
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
return EXAMPLE_OBJECT_PROXY (g_object_new (EXAMPLE_TYPE_OBJECT_PROXY, "g-connection", connection, "g-object-path", object_path, NULL));
}
/**
- ExampleObjectSkeleton:
- The #ExampleObjectSkeleton structure contains only private data and should only be accessed using the provided API.
*/
/**
- ExampleObjectSkeletonClass:
- @parent_class: The parent class.
- Class structure for #ExampleObjectSkeleton.
*/
static void
example_object_skeleton__example_object_iface_init (ExampleObjectIface *iface G_GNUC_UNUSED)
{
}
static void
example_object_skeleton__g_dbus_object_iface_init (GDBusObjectIface *iface)
{
iface->interface_added = example_object_notify;
iface->interface_removed = example_object_notify;
}
G_DEFINE_TYPE_WITH_CODE (ExampleObjectSkeleton, example_object_skeleton, G_TYPE_DBUS_OBJECT_SKELETON,
G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_OBJECT, example_object_skeleton__example_object_iface_init)
G_IMPLEMENT_INTERFACE (G_TYPE_DBUS_OBJECT, example_object_skeleton__g_dbus_object_iface_init))
static void
example_object_skeleton_init (ExampleObjectSkeleton *object G_GNUC_UNUSED)
{
}
static void
example_object_skeleton_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ExampleObjectSkeleton *object = EXAMPLE_OBJECT_SKELETON (gobject);
GDBusInterfaceSkeleton *interface;
switch (prop_id)
{
case 1:
interface = g_value_get_object (value);
if (interface != NULL)
{
g_warn_if_fail (EXAMPLE_IS_ANIMAL (interface));
g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object), interface);
}
else
{
g_dbus_object_skeleton_remove_interface_by_name (G_DBUS_OBJECT_SKELETON (object), "org.gtk.GDBus.Example.ObjectManager.Animal");
}
break;
cmake_minimum_required(VERSION 3.16)
project(dbus_test)
aux_source_directory(. SRCS)
add_executable(test ${SRCS})
target_link_libraries(test dbus-1)
3
}
}
static void
example_object_skeleton_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ExampleObjectSkeleton *object = EXAMPLE_OBJECT_SKELETON (gobject);
GDBusInterface *interface;
switch (prop_id)
{
case 1:
interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), "org.gtk.GDBus.Example.ObjectManager.Animal");
g_value_take_object (value, interface);
break;
cmake_minimum_required(VERSION 3.16)
project(dbus_test)
aux_source_directory(. SRCS)
add_executable(test ${SRCS})
target_link_libraries(test dbus-1)
2
}
}
static void
example_object_skeleton_class_init (ExampleObjectSkeletonClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = example_object_skeleton_set_property;
gobject_class->get_property = example_object_skeleton_get_property;
g_object_class_override_property (gobject_class, 1, "animal");
g_object_class_override_property (gobject_class, 2, "cat");
}
/**
- example_object_skeleton_new:
- @object_path: An object path.
- Creates a new skeleton object.
- Returns: (transfer full): The skeleton object.
*/
ExampleObjectSkeleton *
example_object_skeleton_new (const gchar *object_path)
{
g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
return EXAMPLE_OBJECT_SKELETON (g_object_new (EXAMPLE_TYPE_OBJECT_SKELETON, "g-object-path", object_path, NULL));
}
/**
- example_object_skeleton_set_animal:
- @object: A #ExampleObjectSkeleton.
- @interface_: (nullable): A #ExampleAnimal or %NULL to clear the interface.
- Sets the #ExampleAnimal instance for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link> on @object.
- Since: 2.30
*/
void example_object_skeleton_set_animal (ExampleObjectSkeleton *object, ExampleAnimal *interface_)
{
g_object_set (G_OBJECT (object), "animal", interface_, NULL);
}
/**
- example_object_skeleton_set_cat:
- @object: A #ExampleObjectSkeleton.
- @interface_: (nullable): A #ExampleCat or %NULL to clear the interface.
- Sets the #ExampleCat instance for the D-Bus interface <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Cat.top_of_page">org.gtk.GDBus.Example.ObjectManager.Cat</link> on @object.
*/
void example_object_skeleton_set_cat (ExampleObjectSkeleton *object, ExampleCat *interface_)
{
g_object_set (G_OBJECT (object), "cat", interface_, NULL);
}
/* ------------------------------------------------------------------------
- Code for ObjectManager client
-
*/
/**
- SECTION:ExampleObjectManagerClient
- @title: ExampleObjectManagerClient
- @short_description: Generated GDBusObjectManagerClient type
- This section contains a #GDBusObjectManagerClient that uses example_object_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc.
*/
/**
- ExampleObjectManagerClient:
- The #ExampleObjectManagerClient structure contains only private data and should only be accessed using the provided API.
*/
/**
- ExampleObjectManagerClientClass:
- @parent_class: The parent class.
- Class structure for #ExampleObjectManagerClient.
*/
G_DEFINE_TYPE (ExampleObjectManagerClient, example_object_manager_client, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT)
static void
example_object_manager_client_init (ExampleObjectManagerClient *manager G_GNUC_UNUSED)
{
}
static void
example_object_manager_client_class_init (ExampleObjectManagerClientClass *klass G_GNUC_UNUSED)
{
}
/**
- example_object_manager_client_get_proxy_type:
- @manager: A #GDBusObjectManagerClient.
- @object_path: The object path of the remote object (unused).
- @interface_name: (nullable): Interface name of the remote object or %NULL to get the object proxy #GType.
- @user_data: User data (unused).
- A #GDBusProxyTypeFunc that maps @interface_name to the generated #GDBusObjectProxy derived and #GDBusProxy derived types.
- Returns: A #GDBusProxy derived #GType if @interface_name is not %NULL, otherwise the #GType for #ExampleObjectProxy.
*/
GType
example_object_manager_client_get_proxy_type (GDBusObjectManagerClient *manager G_GNUC_UNUSED, const gchar *object_path G_GNUC_UNUSED, const gchar *interface_name, gpointer user_data G_GNUC_UNUSED)
{
static gsize once_init_value = 0;
static GHashTable *lookup_hash;
GType ret;
if (interface_name == NULL)
return EXAMPLE_TYPE_OBJECT_PROXY;
if (g_once_init_enter (&once_init_value))
{
lookup_hash = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (lookup_hash, (gpointer) "org.gtk.GDBus.Example.ObjectManager.Animal", GSIZE_TO_POINTER (EXAMPLE_TYPE_ANIMAL_PROXY));
g_hash_table_insert (lookup_hash, (gpointer) "org.gtk.GDBus.Example.ObjectManager.Cat", GSIZE_TO_POINTER (EXAMPLE_TYPE_CAT_PROXY));
g_once_init_leave (&once_init_value, 1);
}
ret = (GType) GPOINTER_TO_SIZE (g_hash_table_lookup (lookup_hash, interface_name));
if (ret == (GType) 0)
ret = G_TYPE_DBUS_PROXY;
return ret;
}
/**
- example_object_manager_client_new:
- @connection: A #GDBusConnection.
- @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.
- @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @callback: A #GAsyncReadyCallback to call when the request is satisfied.
- @user_data: User data to pass to @callback.
- Asynchronously creates #GDBusObjectManagerClient using example_object_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new() for more details.
- When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).
- You can then call example_object_manager_client_new_finish() to get the result of the operation.
- See example_object_manager_client_new_sync() for the synchronous, blocking version of this constructor.
*/
void
example_object_manager_client_new (
GDBusConnection *connection,
GDBusObjectManagerClientFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_async_initable_new_async (EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", example_object_manager_client_get_proxy_type, NULL);
}
/**
- example_object_manager_client_new_finish:
- @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_object_manager_client_new().
- @error: Return location for error or %NULL
- Finishes an operation started with example_object_manager_client_new().
- Returns: (transfer full) (type ExampleObjectManagerClient): The constructed object manager client or %NULL if @error is set.
*/
GDBusObjectManager *
example_object_manager_client_new_finish (
GAsyncResult *res,
GError **error)
{
GObject *ret;
GObject *source_object;
source_object = g_async_result_get_source_object (res);
ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
g_object_unref (source_object);
if (ret != NULL)
return G_DBUS_OBJECT_MANAGER (ret);
else
return NULL;
}
/**
- example_object_manager_client_new_sync:
- @connection: A #GDBusConnection.
- @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.
- @name: (nullable): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @error: Return location for error or %NULL
- Synchronously creates #GDBusObjectManagerClient using example_object_manager_client_get_proxy_type() as the #GDBusProxyTypeFunc. See g_dbus_object_manager_client_new_sync() for more details.
- The calling thread is blocked until a reply is received.
- See example_object_manager_client_new() for the asynchronous version of this constructor.
- Returns: (transfer full) (type ExampleObjectManagerClient): The constructed object manager client or %NULL if @error is set.
*/
GDBusObjectManager *
example_object_manager_client_new_sync (
GDBusConnection *connection,
GDBusObjectManagerClientFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error)
{
GInitable *ret;
ret = g_initable_new (EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "connection", connection, "object-path", object_path, "get-proxy-type-func", example_object_manager_client_get_proxy_type, NULL);
if (ret != NULL)
return G_DBUS_OBJECT_MANAGER (ret);
else
return NULL;
}
/**
- example_object_manager_client_new_for_bus:
- @bus_type: A #GBusType.
- @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.
- @name: A bus name (well-known or unique).
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @callback: A #GAsyncReadyCallback to call when the request is satisfied.
- @user_data: User data to pass to @callback.
- Like example_object_manager_client_new() but takes a #GBusType instead of a #GDBusConnection.
- When the operation is finished, @callback will be invoked in the thread-default main loop of the thread you are calling this method from (see g_main_context_push_thread_default()).
- You can then call example_object_manager_client_new_for_bus_finish() to get the result of the operation.
- See example_object_manager_client_new_for_bus_sync() for the synchronous, blocking version of this constructor.
*/
void
example_object_manager_client_new_for_bus (
GBusType bus_type,
GDBusObjectManagerClientFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_async_initable_new_async (EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", example_object_manager_client_get_proxy_type, NULL);
}
/**
- example_object_manager_client_new_for_bus_finish:
- @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_object_manager_client_new_for_bus().
- @error: Return location for error or %NULL
- Finishes an operation started with example_object_manager_client_new_for_bus().
- Returns: (transfer full) (type ExampleObjectManagerClient): The constructed object manager client or %NULL if @error is set.
*/
GDBusObjectManager *
example_object_manager_client_new_for_bus_finish (
GAsyncResult *res,
GError **error)
{
GObject *ret;
GObject *source_object;
source_object = g_async_result_get_source_object (res);
ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
g_object_unref (source_object);
if (ret != NULL)
return G_DBUS_OBJECT_MANAGER (ret);
else
return NULL;
}
/**
- example_object_manager_client_new_for_bus_sync:
- @bus_type: A #GBusType.
- @flags: Flags from the #GDBusObjectManagerClientFlags enumeration.
- @name: A bus name (well-known or unique).
- @object_path: An object path.
- @cancellable: (nullable): A #GCancellable or %NULL.
- @error: Return location for error or %NULL
- Like example_object_manager_client_new_sync() but takes a #GBusType instead of a #GDBusConnection.
- The calling thread is blocked until a reply is received.
- See example_object_manager_client_new_for_bus() for the asynchronous version of this constructor.
- Returns: (transfer full) (type ExampleObjectManagerClient): The constructed object manager client or %NULL if @error is set.
*/
GDBusObjectManager *
example_object_manager_client_new_for_bus_sync (
GBusType bus_type,
GDBusObjectManagerClientFlags flags,
const gchar *name,
const gchar *object_path,
GCancellable *cancellable,
GError **error)
{
GInitable *ret;
ret = g_initable_new (EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, cancellable, error, "flags", flags, "name", name, "bus-type", bus_type, "object-path", object_path, "get-proxy-type-func", example_object_manager_client_get_proxy_type, NULL);
if (ret != NULL)
return G_DBUS_OBJECT_MANAGER (ret);
else
return NULL;
}
↩