D-BUS、GDBUS简述
2025-08-22 16:08:05,

D-BUS、GDBUS简述

D-BUS、GDBUS简述

D-BUS简述

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)
    特性 Session Bus System Bus
    启动时机 用户登录时 系统启动时(由 systemd 管理)
    权限 用户级权限 root 权限
    配置文件 session.conf,用户级服务描述文件 system.conf,系统服务描述文件
    典型应用 桌面应用集成(如通知系统) 硬件事件(如 USB 插入)、系统服务通信
    地址固定性 动态地址(环境变量指定) 固定地址(/var/run/dbus/system_bus_socket
  • dbus-daemon(消息总线守护进程

    • dbus-daemon与session bus是一一对应的,每个活跃的用户会话(Session)都拥有一个独立的 dbus-daemon 进程,专门负责管理该会话内的所有消息路由和服务注册。二者是同一实体的逻辑与物理表现。
    • 此进程的生命周期与用户会话绑定:用户登录时创建,用户注销时终止。
    • system bus同样有一个对应的dbus-daemon。

消息

  • dbus中的消息有四种类型:

    • method call
    • method return
    • signal
    • error
  • signal与method的区别:

    • signal是一对多,method是一对一
    • signal是单向的,不返回。method消息发出后,发出方会收到返回消息。

对象路径、接口

  • 连接(Bus name)标识与会话总线的连接,表示一个dbus服务

  • 对象路径(Object Path)唯一标识服务中的对象实例(类似文件路径),标识资源的路径。命名规则:采用斜杠分隔的层次结构,如 /org/kde/Device1

  • 接口名称(Interface Name),定义对象的能力契约,包含方法、信号和属性(类似抽象类)。可以被不同的对象实现。采用反向域名格式(如 org.freedesktop.DBus.Properties),需在总线范围内唯一。接口与对象是解耦的,二者名称并不需要严格对应。

  • 方法和信号隶属于接口。

层级关系

Bus name -》Path-》Interface-》Method/Signal

D-BUS使用

  • 安装:sudo apt install dbus

  • 包含头文件:#include <dbus/dbus.h>

  • signal

    • 发送方步骤:

      1. 建立与会话总线的连接
      2. 给该连接注册名称(可选)
      3. 创建信号
      4. 发送信号
      5. 释放资源
    • 接收方步骤:

      1. 建立与会话总线的连接
      2. 给该连接注册名称(可选)
      3. 添加监听匹配规则(需要发送方的接口名、信号名,以及路径(可选),如果给定路径,则只接收该路径对象的信号,否则接收所有实现该接口的对象信号)
      4. 循环监听
      5. 信号参数解析
  • method_call & method_reply

    • 被调用方步骤:

      1. 建立连接

      2. 注册连接名称(必须)

      3. 循环监听

      4. 解析调用消息并处理

        1. 读取消息中携带的参数,进行相应的处理
        2. 创建返回消息,将处理结果传入返回消息变量中
        3. 发送返回消息
    • 调用方步骤:

      1. 建立连接
      2. 注册连接名称
      3. 创建调用消息(需要被调用方的连接名、对象路径、接口名和方法名),给定调用参数
      4. 发送消息
      5. 接收响应

信号发送接收示例

发送

#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(&amp;err);  // 初始化错误结构体
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err );  // 获取一个与session bus的连接
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionErr : %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
	return -1;

// 步骤2:给连接注册一个名字,这个步骤不是必须的

if 1

ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
	return -1;

endif

// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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

    • 类型:dbus_uint32_t ,实质就是无符号32位整数
    • 作用:可选参数。若传入非 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(&amp;err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
return;

// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;

// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
		if(!dbus_message_iter_init(msg, &amp;arg))
			fprintf(stderr, &quot;MessageHas no Param&quot;);
		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
			fprintf(stderr, &quot;Param isnot string&quot;);
		else
			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
		printf(&quot;Got Singal withvalue : %s\n&quot;, sigvalue);
	}
	dbus_message_unref(msg);
}//End of while

}

int main(int argc, char **argv){
listen_signal();
return 0;
}

编译

CMakeLists.txt

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,原因:

      • 默认安装的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, &param1);
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, &param2);
}

printf(&quot;receive method call, param is %d and %d\n&quot;, param1, param2);
int result = param1 + param2;

// 2 创建返回消息reply
reply = dbus_message_new_method_return(msg);
// 通过消息迭代器在返回消息中填入结果
dbus_message_iter_init_append(reply, &amp;iter);
if(!dbus_message_iter_append_basic(&amp;iter, DBUS_TYPE_INT32, &amp;result)){
	printf(&quot;Out ofMemory!\n&quot;);
	exit(1);
}

// 3 发送返回消息
if(!dbus_connection_send(conn, reply, &amp;serial)){
	printf(&quot;Out of Memory\n&quot;);
	exit(1);
}
dbus_connection_flush(conn);
dbus_message_unref(reply);

}

void listen_dbus()
{
DBusMessage *msg;
DBusConnection *connection;
DBusError err;

// 步骤1 建立连接
dbus_error_init(&amp;err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
    fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    dbus_error_free(&amp;err);
}
if(connection == NULL)
    return; 

// 步骤2 设置连接名
int ret = dbus_bus_request_name(connection, &quot;org.example.MethodCallable&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
    fprintf(stderr, &quot;Name Error %s\n&quot;, err.message);
    dbus_error_free(&amp;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), &quot;/org/example/MethodService/Object&quot;) == 0){
		if(dbus_message_is_method_call(msg, &quot;org.example.MethodService.Add&quot;, &quot;AddMethod&quot;)){
			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(&amp;err);	
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionErr : %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
	return NULL;

// 步骤2 注册连接名称
ret = dbus_bus_request_name(connection, &quot;org.example.MethodCall&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;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(&amp;err);
msg = dbus_message_new_method_call(&quot;org.example.MethodCallable&quot;, &quot;/org/example/MethodService/Object&quot;, 
    &quot;org.example.MethodService.Add&quot;, &quot;AddMethod&quot;);
if(msg == NULL){
	fprintf(stderr, &quot;MessageNULL&quot;);
	return;
}

// 给定调用参数
dbus_message_iter_init_append(msg, &amp;iter);
if(!dbus_message_iter_append_basic(&amp;iter, DBUS_TYPE_INT32, &amp;param1)){
	fprintf(stderr, &quot;Out of Memory!&quot;);
	exit(1);
}

if(!dbus_message_iter_append_basic(&amp;iter, DBUS_TYPE_INT32, &amp;param2)){
	fprintf(stderr, &quot;Out of Memory!&quot;);
	exit(1);
}

// 步骤4 发送消息,pending用于接收调用后的方法响应
if(!dbus_connection_send_with_reply(connection, msg, &amp;pending, -1)){
	fprintf(stderr, &quot;Out of Memory!&quot;);
	exit(1);
}

if(pending == NULL){
	fprintf(stderr, &quot;Pending CallNULL: connection is disconnected &quot;);
	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, &quot;ReplyNull\n&quot;);
	exit(1);
}
dbus_pending_call_unref(pending);
// 读取响应数据
if(!dbus_message_iter_init(msg, &amp;iter))
	fprintf(stderr, &quot;Message has no ret!\n&quot;);
else if (dbus_message_iter_get_arg_type(&amp;iter) != DBUS_TYPE_INT32)
	fprintf(stderr, &quot;Argument is not integer!\n&quot;);
else
	dbus_message_iter_get_basic(&amp;iter, &amp;result);

printf(&quot;Got Reply: %d\n&quot;, result);
dbus_message_unref(msg);

}

int main()
{
send_a_method_call(connect_dbus(), 5, 10);

ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
	return -1;
0

}

GDBUS

reference

Gio – 2.0: 迁移到 GDBus - GTK 文档

常用函数

g_bus_own_name

声明
ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
	return -1;
1
描述

连接到bus_type指定的总线,并在该总线注册一个连接名称,在总线获取成功时调用bus_acquired_handler,并分别在名称获取或丢失时调用name_acquired_handlername_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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;err);
      }
      if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
      	return -1;
      2
    • 说明:在连接到类型为bus_type的总线或NULL时调用的处理程序。

  • name_acquired_handler

    • 类型:

      ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;err);
      }
      if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
      	return -1;
      3
    • 说明:在名称被获取时调用。

  • name_lost_handler

    • 类型:

      ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;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文件内容生成的名称,会作为所有生成的函数或是宏的名称的前缀。其中examplegdbus-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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;err);
      }
      if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
      	return -1;
      8

      形式的结构体赋值语句,结构体的原型为

      ret = dbus_bus_request_name(connection, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
      if(dbus_error_is_set(&amp;err)){
      	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
      	dbus_error_free(&amp;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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
      	fprintf(stderr, &quot;MessageNULL\n&quot;);
      	return -1;
      }
      // 给这个messge具体的内容
      dbus_message_iter_init_append(msg, &amp;arg);
      if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
      	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
      	return -1;
      }
      
      // 步骤4: 将信号通过连接发送
      if(!dbus_connection_send(connection, msg, &amp;serial)){
      	fprintf(stderr, &quot;Out of Memory!\n&quot;);
      	return -1;
      }
      dbus_connection_flush(connection);
      printf(&quot;Signal Send\n&quot;);
      
      // 步骤5: 释放资源。
      dbus_message_unref(msg);
      return 0;
      0

      形式的函数指针。要使用G_CALLBACK转换该函数指针。

    • 具体说明:相较于生成的头文件中struct _ExampleAnimalIface

      // 步骤3:发送一个信号
      // 创建message,message参数中包含这个信号的路径,接口,以及信号名
      if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
      	fprintf(stderr, &quot;MessageNULL\n&quot;);
      	return -1;
      }
      // 给这个messge具体的内容
      dbus_message_iter_init_append(msg, &amp;arg);
      if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
      	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
      	return -1;
      }
      
      // 步骤4: 将信号通过连接发送
      if(!dbus_connection_send(connection, msg, &amp;serial)){
      	fprintf(stderr, &quot;Out of Memory!\n&quot;);
      	return -1;
      }
      dbus_connection_flush(connection);
      printf(&quot;Signal Send\n&quot;);
      
      // 步骤5: 释放资源。
      dbus_message_unref(msg);
      return 0;
      1

      内定义的handle_poke函数指针,该函数中多了一个gpointer类型的参数,gpointer实质是void*类型,用于传递自定义的一些数据。此处的函数指针名称不作要求,但一般形式都是on_接口名_方法名

  • data

    • 类型:gpointer
    • 用于传递自定义的一些数据,如不需要,可为NULL

g_main_loop_new

声明
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
4
描述

通过一个 GMainLoop 对象的引用次数减一。如果结果是零,则释放循环及其所有相关内存。

g_main_loop_quit

声明
// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
5
描述

停止 GMainLoop 的运行。对于此循环的任何 g\_main\_loop\_run() 调用都将返回。

注意,当调用 g\_main\_loop\_quit() 时,已调度的事件源仍将被执行。

流程

服务端流程

  1. g_main_loop_new创建主事件循环对象
  2. g_bus_own_name创建连接并注册连接名称,且注册回调函数(所有事件都在回调函数中处理)
  3. g_main_loop_run启动主事件循环
  4. g_bus_unown_name停止拥有之前注册的连接名称
  5. g_main_loop_unref释放主事件循环对象资源

客户端流程

  1. g_main_loop_new创建主事件循环对象
  2. example_object_manager_client_new_for_bus_sync同步创建并返回一个对象管理代理客户端(该函数是gdbus-codegen根据XML文件生成的头文件和源文件中包含的函数,并且有异步版本)
  3. 使用上一步获取到的对象管理代理客户端,进行方法调用,以及可选的连接该对象的信号和回调函数。
  4. g_main_loop_run启动主事件循环
  5. 停止循环,释放资源

编码流程

  1. 创建XML文件,在其中写定接口,接口中包含方法、信号、属性等定义;

  2. 使用gdbus-codegen工具根据XML文件生成代码,包括一个头文件和一个源文件;

  3. 引入生成的头文件,利用其中包含的函数和宏等编写代码;

  4. 编译运行。

示例代码

gdbus-example-objectmanager.xml

// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤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, &quot;org.example.SignalSource&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr,&quot;Name Err :%s\n&quot;, err.message);
	dbus_error_free(&amp;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

编译过程

  1. 首先使用gdbus-codegen生成代码。

    dbus_bool_t dbus_connection_send(
        DBusConnection *connection,  // D-Bus 连接对象指针
        DBusMessage    *message,     // 待发送的消息对象指针
        dbus_uint32_t  *serial       // 返回消息序列号(可选)
    );
    8

  2. 创建gdbus客户端和服务端程序

  3. 创建CMakeLists.txt

  4. 创建build文件夹,进入build文件夹,cmake ..,然后make

运行

先执行服务端程序,再执行客户端程序。

关于gdbus-codegen生成的代码的介绍

生成的代码中包括了绝大多数我们在开发gdbus程序中需要的函数或者别的一些信息。以上文中的XML文件生成的代码举例说明,由于生成的代码文件很大,仅挑选一些片段在此。完整版见gdbus-codegen生成代码1

// 步骤3:发送一个信号
// 创建message,message参数中包含这个信号的路径,接口,以及信号名
if((msg = dbus_message_new_signal(&quot;/org/example/SignalService/Sender&quot;, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;))== NULL){
	fprintf(stderr, &quot;MessageNULL\n&quot;);
	return -1;
}
// 给这个messge具体的内容
dbus_message_iter_init_append(msg, &amp;arg);
if(!dbus_message_iter_append_basic(&amp;arg, DBUS_TYPE_STRING, &amp;sigvalue)){
	fprintf(stderr, &quot;Out OfMemory!\n&quot;);
	return -1;
}

// 步骤4: 将信号通过连接发送
if(!dbus_connection_send(connection, msg, &amp;serial)){
	fprintf(stderr, &quot;Out of Memory!\n&quot;);
	return -1;
}
dbus_connection_flush(connection);
printf(&quot;Signal Send\n&quot;);

// 步骤5: 释放资源。
dbus_message_unref(msg);
return 0;
1

  • 该结构体中,几乎是直接给出了handle_pokejumped信号的回调函数声明,真正的回调函数也只需要在参数列表中增加一个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(&amp;err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
return;

// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;

// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
		if(!dbus_message_iter_init(msg, &amp;arg))
			fprintf(stderr, &quot;MessageHas no Param&quot;);
		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
			fprintf(stderr, &quot;Param isnot string&quot;);
		else
			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
return;

// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;

// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
		if(!dbus_message_iter_init(msg, &amp;arg))
			fprintf(stderr, &quot;MessageHas no Param&quot;);
		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
			fprintf(stderr, &quot;Param isnot string&quot;);
		else
			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(connection == NULL)
return;

// 步骤2:给连接注册一个名称,非必需但推荐
ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
	dbus_error_free(&amp;err);
}
if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
return;

// 步骤3:添加监听匹配规则
dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
if(dbus_error_is_set(&amp;err)){
	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
		if(!dbus_message_iter_init(msg, &amp;arg))
			fprintf(stderr, &quot;MessageHas no Param&quot;);
		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
			fprintf(stderr, &quot;Param isnot string&quot;);
		else
			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
		printf(&quot;Got Singal withvalue : %s\n&quot;, sigvalue);
	}
	dbus_message_unref(msg);
}//End of while
2

  • 以上代码给出了XML文件接口中定义的方法的相关信息,"Poke"是定义的方法名,"handle-poke"是为该方法生成的信号名。
  1. 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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 (&paramv[n], G_TYPE_VARIANT);
    g_value_set_variant (&paramv[n], child);
    n++;
    }
    else
    g_dbus_gvariant_to_gvalue (child, &paramv[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 (&paramv[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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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 (&paramv[0], EXAMPLE_TYPE_CAT);
    g_value_set_object (&paramv[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 (&paramv[n], G_TYPE_VARIANT);
    g_value_set_variant (&paramv[n], child);
    n++;
    }
    else
    g_dbus_gvariant_to_gvalue (child, &paramv[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 (&paramv[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 (&paramv[n], EXAMPLE_TYPE_CAT);
    g_value_set_object (&paramv[n++], skeleton);
    g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);
    g_value_set_object (&paramv[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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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(&amp;err);
    connection = dbus_bus_get(DBUS_BUS_SESSION, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;ConnectionError %s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(connection == NULL)
    return;
    
    // 步骤2:给连接注册一个名称,非必需但推荐
    ret = dbus_bus_request_name(connection, &quot;org.example.SignalReceiver&quot;, DBUS_NAME_FLAG_REPLACE_EXISTING, &amp;err);
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Name Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
    return;
    
    // 步骤3:添加监听匹配规则
    dbus_bus_add_match(connection, &quot;type='signal', interface='org.example.Signal.Test', path='/org/example/SignalService/Sender'&quot;, &amp;err);
    dbus_connection_flush(connection);  // 立即将规则发送给 dbus-daemon,确保实时生效
    if(dbus_error_is_set(&amp;err)){
    	fprintf(stderr, &quot;Match Error%s\n&quot;, err.message);
    	dbus_error_free(&amp;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, &quot;org.example.Signal.Test&quot;, &quot;Test&quot;)){
    		if(!dbus_message_iter_init(msg, &amp;arg))
    			fprintf(stderr, &quot;MessageHas no Param&quot;);
    		else if(dbus_message_iter_get_arg_type(&amp;arg) != DBUS_TYPE_STRING)
    			fprintf(stderr, &quot;Param isnot string&quot;);
    		else
    			dbus_message_iter_get_basic(&amp;arg, &amp;sigvalue);
    		printf(&quot;Got Singal withvalue : %s\n&quot;, 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 (&paramv[n], G_TYPE_VARIANT);
    g_value_set_variant (&paramv[n], child);
    n++;
    }
    else
    g_dbus_gvariant_to_gvalue (child, &paramv[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 (&paramv[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;
      }