D-BUS、GDBUS【IPC】

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)。

image

消息总线

  • 消息总线分为:

    • 会话总线(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);

return 0;

}

GDBUS

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

GDBUS简述

GDBus是DBus协议的现代C语言实现,属于GLib的一部分,具有以下特点:

  • 独立实现

    GDBus并非基于libdbus,而是重新实现了DBus协议,使用GIO流(GIO Stream)作为传输层,避免了libdbus的多线程问题

  • 类型系统优化

    使用GVariant处理数据(替代dbus-glib的GObject类型系统),完美匹配DBus的二进制数据类型(如整型、字符串、结构体等),简化了数据序列化

  • 异步与集成

    原生支持异步操作(如g_dbus_proxy_call()),避免阻塞主线程,并深度集成GLib事件循环(GMainLoop),适合GUI应用开发

  • 工具链支持

    提供gdbus-codegen工具,根据XML接口描述文件自动生成C代码(如代理类、服务端骨架),减少手写样板代码

维度 DBus(协议) GDBus(实现)
定位 进程间通信规范 GLib库提供的DBus实现
核心实现 多实现并存(libdbus、sd-bus等) 独立实现,基于GIO流
开发便利性 底层API复杂 高层封装,支持异步与代码生成
生态依赖 依赖GLib/GObject
适用场景 所有DBus兼容系统 GNOME应用或深度集成GLib的项目

常用函数

g_bus_own_name

声明
guint
g_bus_own_name (
  GBusType bus_type,
  const gchar* name,
  GBusNameOwnerFlags flags,
  GBusAcquiredCallback bus_acquired_handler,
  GBusNameAcquiredCallback name_acquired_handler,
  GBusNameLostCallback name_lost_handler,
  gpointer user_data,
  GDestroyNotify user_data_free_func
)
描述

连接到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

    • 类型:

      void
      (* GBusAcquiredCallback) (
        GDBusConnection* connection,
        const gchar* name,
        gpointer user_data
      )
      
    • 说明:在连接到类型为bus_type的总线或NULL时调用的处理程序。

  • name_acquired_handler

    • 类型:

      void
      (* GBusNameAcquiredCallback) (
        GDBusConnection* connection,
        const gchar* name,
        gpointer user_data
      )
      
    • 说明:在名称被获取时调用。

  • name_lost_handler

    • 类型:

      void
      (* GBusNameLostCallback) (
        GDBusConnection* connection,
        const gchar* name,
        gpointer user_data
      )
      
    • 说明:当名称丢失或连接被关闭时调用。

  • user_data

    • 类型:gpointer,实质是void*
    • 说明:传递给处理器的用户数据。参数可以是NULL。数据由函数的调用者拥有。
  • user_data_free_func

    • 类型

      void
      (* GDestroyNotify) (
        gpointer data
      )
      
    • 说明:指定在销毁数据元素时调用的函数类型。它将指针传递给数据元素,并应释放为此分配的任何内存和资源。参数可以为 NULL

返回值
  • 类型:guint
  • 说明:一个可用于与 g_bus_unown_name() 一起使用的标识符(永远不会是 0),用于停止拥有该名称。

g_bus_unown_name

声明
void
g_bus_unown_name (
  guint owner_id
)
描述

停止拥有一个名称。

参数
  • owner_id
    g_bus_own_name的返回值

g_signal_connect

声明
#define g_signal_connect (
  instance,
  detailed_signal,
  c_handler,
  data
)
说明:

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生成的代码中查找信号名,形如

      static const _ExtendedGDBusMethodInfo _example_animal_method_info_poke =
      {
        {
          -1,
          (gchar *) "Poke",
          (GDBusArgInfo **) &_example_animal_method_info_poke_IN_ARG_pointers,
          (GDBusArgInfo **) &_example_animal_method_info_poke_OUT_ARG_pointers,
          NULL
        },
        "handle-poke",
        FALSE
      };
      

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

      typedef struct
      {
        GDBusMethodInfo parent_struct;
        const gchar *signal_name;
        gboolean pass_fdlist;
      } _ExtendedGDBusMethodInfo;
      

      也就是说,"handle-poke"就是生成代码为Poke方法创建的信号。

  • c_handler

    • 类型:形如

      static gboolean on_animal_poke (
          ExampleAnimal *object,
          GDBusMethodInvocation *invocation,
          gboolean arg_make_sad,
          gboolean arg_make_happy,
      	gpointer user_data
      	)
      

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

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

      struct _ExampleAnimalIface
      {
        GTypeInterface parent_iface;
      

      gboolean (*handle_poke) (
      ExampleAnimal *object,
      GDBusMethodInvocation *invocation,
      gboolean arg_make_sad,
      gboolean arg_make_happy);

      const gchar * (*get_foo) (ExampleAnimal *object);

      const gchar * (*get_mood) (ExampleAnimal *object);

      void (*jumped) (
      ExampleAnimal *object,
      gdouble arg_height);

      const gchar * (*get_bar) (ExampleAnimal *object);

      };

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

  • data

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

g_main_loop_new

声明
GMainLoop*
g_main_loop_new (
  GMainContext* context,
  gboolean is_running
)
描述

创建一个新的 GMainLoop 结构体。GMainLoop 结构是一个不透明的数据类型,它表示 GLib 或 GTK 应用程序的主事件循环。

参数
  • context

    • 类型:GMainContext*GMainContext 结构体是不透明的数据类型,用于表示要主循环中处理的一组源。
    • 说明:此参数可以为NULL,如果为 NULL,将使用全局默认的主上下文。数据由函数的调用者持有。
  • is_running

    • 设置为 TRUE 以指示循环正在运行。这并不很重要,因为调用 g\_main\_loop\_run() 无论如何都会将其设置为 TRUE
返回值
  • 类型:GMainLoop
  • 说明:一个新的 GMainLoop。函数的调用者负责数据的所有权,并负责释放它。

g_main_loop_run

声明
void
g_main_loop_run (
  GMainLoop* loop
)
描述

运行主循环,直到在循环上调用 g\_main\_loop\_quit()。如果这是在循环的 GMainContext 线程上调用,它将处理循环的事件,否则它将只等待。

参数
  • loop

    g_main_loop_new返回的对象

g_main_loop_unref

声明
void
g_main_loop_unref (
  GMainLoop* loop
)
描述

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

g_main_loop_quit

声明
void
g_main_loop_quit (
  GMainLoop* loop
)
描述

停止 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

<node>
  <!-- org.gtk.GDBus.Example.ObjectManager.Animal:
       @short_description: Example docs generated by gdbus-codegen
       @since: 2.30
   This D-Bus interface is used to describe a simple animal.
--&gt;

<interface name="org.gtk.GDBus.Example.ObjectManager.Animal">
<!-- Mood: The mood of the animal.
@since: 2.30

     Known values for this property include
     &lt;literal&gt;Happy&lt;/literal&gt; and &lt;literal&gt;Sad&lt;/literal&gt;. Use the
     org.gtk.GDBus.Example.ObjectManager.Animal.Poke() method to
     change this property.

     This property influences how often the animal jumps up and
     down, see the
     #org.gtk.GDBus.Example.ObjectManager.Animal::Jumped signal
     for more details.
--&gt;
&lt;property name=&quot;Mood&quot; type=&quot;s&quot; access=&quot;read&quot;/&gt;

&lt;!--
    Poke:
    @make_sad: Whether to make the animal sad.
    @make_happy: Whether to make the animal happy.
    @since: 2.30

    Method used to changing the mood of the animal. See also the
    #org.gtk.GDBus.Example.ObjectManager.Animal:Mood property.
  --&gt;
&lt;method name=&quot;Poke&quot;&gt;
  &lt;arg direction=&quot;in&quot; type=&quot;b&quot; name=&quot;make_sad&quot;/&gt;
  &lt;arg direction=&quot;in&quot; type=&quot;b&quot; name=&quot;make_happy&quot;/&gt;
  &lt;arg direction=&quot;out&quot; type=&quot;b&quot; name=&quot;result&quot;/&gt;
&lt;/method&gt;

&lt;!--
    Jumped:
    @height: Height, in meters, that the animal jumped.
    @since: 2.30

    Emitted when the animal decides to jump.
  --&gt;
&lt;signal name=&quot;Jumped&quot;&gt;
  &lt;arg type=&quot;d&quot; name=&quot;height&quot;/&gt;
&lt;/signal&gt;

&lt;!--
    Foo:
    Property with no &lt;quote&gt;since&lt;/quote&gt; annotation (should inherit the 2.30 from its containing interface).
  --&gt;
&lt;property name=&quot;Foo&quot; type=&quot;s&quot; access=&quot;read&quot;/&gt;

&lt;!--
    Bar:
    @since: 2.36
    Property with a later &lt;quote&gt;since&lt;/quote&gt; annotation.
  --&gt;
&lt;property name=&quot;Bar&quot; type=&quot;s&quot; access=&quot;read&quot;/&gt;

</interface>

<!-- org.gtk.GDBus.Example.ObjectManager.Cat:
@short_description: More example docs generated by gdbus-codegen

   This D-Bus interface is used to describe a cat. Right now there
   are no properties, methods or signals associated with this
   interface so it is essentially a &lt;ulink
   url=&quot;http://en.wikipedia.org/wiki/Marker_interface_pattern&quot;&gt;Marker
   Interface&lt;/ulink&gt;.

   Note that D-Bus objects implementing this interface also
   implement the #org.gtk.GDBus.Example.ObjectManager.Animal
   interface.
--&gt;

<interface name="org.gtk.GDBus.Example.ObjectManager.Cat">
</interface>
</node>

gdbus-example-server.c

#include "generated-code.h"
#include <gio/gio.h>

/* ---------------------------------------------------------------------------------------------------- */

static GDBusObjectManagerServer *manager = NULL;
// handle-poke信号对应的回调函数
static gboolean
on_animal_poke(ExampleAnimal *animal,
GDBusMethodInvocation *invocation,
gboolean make_sad,
gboolean make_happy,
gboolean result,
gpointer user_data)
{
g_print("receive call!\n");
if ((make_sad && make_happy) || (!make_sad && !make_happy))
{
g_dbus_method_invocation_return_dbus_error(invocation,
"org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
"Exactly one of make_sad or make_happy must be TRUE");
goto out;
}

if (make_sad)
{
    if (g_strcmp0(example_animal_get_mood(animal), &quot;Sad&quot;) == 0)
    {
        g_dbus_method_invocation_return_dbus_error(invocation,
                                                   &quot;org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad&quot;,
                                                   &quot;Sad animal is already sad&quot;);
        goto out;
    }
    result = TRUE;
    g_print(&quot;set_mood!\n&quot;);
    example_animal_set_mood(animal, &quot;Sad&quot;);
    g_print(&quot;complete_poke!\n&quot;);
    example_animal_complete_poke(animal, invocation, result);
    static gdouble height = 0.0;
    height += 10.0; // Increment height for each poke
    g_print(&quot;emit_jumped!\n&quot;);
    example_animal_emit_jumped(animal, height); // Emit the jumped signal with a height of 55.55
    goto out;
}

if (make_happy)
{
    if (g_strcmp0(example_animal_get_mood(animal), &quot;Happy&quot;) == 0)
    {
        g_dbus_method_invocation_return_dbus_error(invocation,
                                                   &quot;org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy&quot;,
                                                   &quot;Happy animal is already happy&quot;);
        goto out;
    }

    example_animal_set_mood(animal, &quot;Happy&quot;);
    example_animal_complete_poke(animal, invocation, result);
    goto out;
}

g_assert_not_reached();

out:
return TRUE;
}

static void
on_bus_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
ExampleObjectSkeleton *object;
guint n;

g_print(&quot;Acquired a message bus connection\n&quot;);

/* Create a new org.freedesktop.DBus.ObjectManager rooted at /example/Animals */
manager = g_dbus_object_manager_server_new(&quot;/example/Animals&quot;);

for (n = 0; n &lt; 10; n++)
{
    gchar *s;
    ExampleAnimal *animal;

    /* Create a new D-Bus object at the path /example/Animals/N where N is 000..009 */
    s = g_strdup_printf(&quot;/example/Animals/%03d&quot;, n);
    object = example_object_skeleton_new(s);
    g_free(s);

    /* Make the newly created object export the interface
     * org.gtk.GDBus.Example.ObjectManager.Animal (note
     * that @object takes its own reference to @animal).
     */
    animal = example_animal_skeleton_new();
    example_animal_set_mood(animal, &quot;Happy&quot;);
    example_object_skeleton_set_animal(object, animal);
    g_object_unref(animal);

    /* Cats are odd animals - so some of our objects implement the
     * org.gtk.GDBus.Example.ObjectManager.Cat interface in addition
     * to the .Animal interface
     */
    if (n % 2 == 1)
    {
        ExampleCat *cat;
        cat = example_cat_skeleton_new();
        example_object_skeleton_set_cat(object, cat);
        g_object_unref(cat);
    }

    /* Handle Poke() D-Bus method invocations on the .Animal interface */
    g_signal_connect(animal,
                     &quot;handle-poke&quot;,
                     G_CALLBACK(on_animal_poke),
                     NULL); /* user_data */

    /* Export the object (@manager takes its own reference to @object) */
    g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
    g_object_unref(object);
}

/* Export all objects */
g_dbus_object_manager_server_set_connection(manager, connection);

}

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;

loop = g_main_loop_new(NULL, FALSE);

// 连接到会话总线并注册well-known,同时注册相应的回调函数
id = g_bus_own_name(G_BUS_TYPE_SESSION,
                    &quot;org.gtk.GDBus.Examples.ObjectManager&quot;,
                    G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
                        G_BUS_NAME_OWNER_FLAGS_REPLACE,
                    on_bus_acquired,
                    on_name_acquired,
                    on_name_lost,
                    loop,
                    NULL);

g_main_loop_run(loop);

g_bus_unown_name(id);
g_main_loop_unref(loop);

return 0;

}

gdbus-example-client.c

#include "generated-code.h"
#include <gio/gio.h>

/* ---------------------------------------------------------------------------------------------------- */
// jumped信号对应的回调函数
static void
on_jumped_emit(
ExampleAnimal *object,
gdouble arg_height,
gpointer user_data)
{
g_print(" - Jumped signal emitted with height: %f\n", arg_height);
}

// 处理manager中所有接口,包括方法的调用等
static void
handle_objects(GDBusObjectManager *manager)
{
GList *objects; // GList是双向链表
GList *l;

// 打印manager所在的路径
g_print(&quot;Object manager at %s\n&quot;, g_dbus_object_manager_get_object_path(manager));
// 从manager中获取对象链表首位结点
objects = g_dbus_object_manager_get_objects(manager);
// 遍历所有对象
for (l = objects; l != NULL; l = l-&gt;next)
{
    ExampleObject *object = EXAMPLE_OBJECT(l-&gt;data);
    GList *interfaces;
    GList *ll;
    g_print(&quot; - Object at %s\n&quot;, g_dbus_object_get_object_path(G_DBUS_OBJECT(object)));

    // 遍历对象中的所有接口
    interfaces = g_dbus_object_get_interfaces(G_DBUS_OBJECT(object));
    for (ll = interfaces; ll != NULL; ll = ll-&gt;next)
    {
        GDBusInterface *interface = G_DBUS_INTERFACE(ll-&gt;data);
        g_print(&quot;   - Interface %s\n&quot;, g_dbus_interface_get_info(interface)-&gt;name);

        if (EXAMPLE_IS_ANIMAL(interface))
        {
            ExampleAnimal *animal = NULL;
            animal = EXAMPLE_ANIMAL(interface);
            gboolean result = FALSE;
            GError *error = NULL;
            // 同步调用Poke方法
            example_animal_call_poke_sync(animal, TRUE, FALSE, &amp;result, NULL, &amp;error);
            if (error != NULL)
            {
                // 解析错误消息
                g_print(&quot;     - error message: %s\n&quot;, error-&gt;message); // 如 &quot;Sad animal is already sad&quot;
                g_error_free(error);                                   // 释放错误对象
            }
            else
            {
                g_print(&quot;     - call result: %d\n&quot;, result);
                g_signal_connect(animal,
                                 &quot;jumped&quot;,
                                 G_CALLBACK(on_jumped_emit),
                                 NULL);
            }
        }
    }
    g_list_free_full(interfaces, g_object_unref);
}
g_list_free_full(objects, g_object_unref);

}

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;

name_owner = g_dbus_object_manager_client_get_name_owner(manager);
g_print(&quot;name-owner: %s\n&quot;, name_owner);
g_free(name_owner);

}

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;

g_print(&quot;Properties Changed on %s:\n&quot;, g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy)));
g_variant_iter_init(&amp;iter, changed_properties);
while (g_variant_iter_next(&amp;iter, &quot;{&amp;sv}&quot;, &amp;key, &amp;value))
{
    s = g_variant_print(value, TRUE);
    g_print(&quot;  %s -&gt; %s\n&quot;, key, s);
    g_variant_unref(value);
    g_free(s);
}

}

gint main(gint argc, gchar *argv[])
{
GDBusObjectManager *manager;
GMainLoop *loop;
GError *error;
gchar *name_owner;

manager = NULL;
loop = NULL;

loop = g_main_loop_new(NULL, FALSE);

error = NULL;
// 获取/example/Animals下所有实现&quot;org.gtk.GDBus.Examples.ObjectManager&quot;的对象。org.gtk.GDBus.Examples.ObjectManage可以只是完整接口的前缀
manager = example_object_manager_client_new_for_bus_sync(G_BUS_TYPE_SESSION,
                                                         G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
                                                         &quot;org.gtk.GDBus.Examples.ObjectManager&quot;,
                                                         &quot;/example/Animals&quot;,
                                                         NULL, /* GCancellable */
                                                         &amp;error);
if (manager == NULL)
{
    g_printerr(&quot;Error getting object manager client: %s&quot;, error-&gt;message);
    g_error_free(error);
    goto out;
}

// 获取 unique-name并打印
name_owner = g_dbus_object_manager_client_get_name_owner(G_DBUS_OBJECT_MANAGER_CLIENT(manager));
g_print(&quot;name-owner: %s\n&quot;, name_owner);
g_free(name_owner);

// 处理manager中的对象
handle_objects(manager);

// 连接manager中的对象的信号与回调函数
g_signal_connect(manager,
                 &quot;notify::name-owner&quot;,
                 G_CALLBACK(on_notify_name_owner),
                 NULL);
g_signal_connect(manager,
                 &quot;object-added&quot;,
                 G_CALLBACK(on_object_added),
                 NULL);
g_signal_connect(manager,
                 &quot;object-removed&quot;,
                 G_CALLBACK(on_object_removed),
                 NULL);
g_signal_connect(manager,
                 &quot;interface-proxy-properties-changed&quot;,
                 G_CALLBACK(on_interface_proxy_properties_changed),
                 NULL);

g_main_loop_run(loop);

out:
// 释放资源
if (manager != NULL)
g_object_unref(manager);
if (loop != NULL)
g_main_loop_unref(loop);

return 0;

}

CMakeLists

cmake_minimum_required(VERSION 3.16)
project(MyDBusApp)

查找依赖

find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0 gio-unix-2.0 dbus-1)
include_directories(\({GLIB_INCLUDE_DIRS}) link_directories(\){GLIB_LIBRARY_DIRS})

编译主程序

add_executable(server gdbus-example-server.c generated-code.c)
add_executable(client gdbus-example-client.c generated-code.c)

target_link_libraries(server ${GLIB_LIBRARIES})
target_link_libraries(client ${GLIB_LIBRARIES})

编译过程

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

    gdbus-codegen --interface-prefix org.gtk.GDBus.Example.ObjectManager. \
                  --generate-c-code generated-code                        \
                  --c-namespace Example                       \
                  --c-generate-object-manager                 \
                  --generate-docbook generated-docs                       \
                  gdbus-example-objectmanager.xml
    

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

  3. 创建CMakeLists.txt

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

运行

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

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

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

struct _ExampleAnimalIface
{
  GTypeInterface parent_iface;

gboolean (*handle_poke) (
ExampleAnimal *object,
GDBusMethodInvocation *invocation,
gboolean arg_make_sad,
gboolean arg_make_happy);

const gchar * (*get_foo) (ExampleAnimal *object);

const gchar * (*get_mood) (ExampleAnimal *object);

void (*jumped) (
ExampleAnimal *object,
gdouble arg_height);

const gchar * (*get_bar) (ExampleAnimal *object);

};

  • 该结构体中,几乎是直接给出了handle_pokejumped信号的回调函数声明,真正的回调函数也只需要在参数列表中增加一个gpointer user_data参数即可。

#define EXAMPLE_TYPE_CAT (example_cat_get_type ())
#define EXAMPLE_CAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_CAT, ExampleCat))
#define EXAMPLE_IS_CAT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_CAT))
#define EXAMPLE_CAT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), EXAMPLE_TYPE_CAT, ExampleCatIface))
  • 上面的几个宏给出了判断对象类型和将对象类型进行转换的方法

/* 被调用方返回结果 */
void example_animal_complete_poke (
    ExampleAnimal *object,
    GDBusMethodInvocation *invocation,
    gboolean result);

/* D-Bus signal emissions functions: */
void example_animal_emit_jumped (
ExampleAnimal *object,
gdouble arg_height);

/* D-Bus method calls: */
void example_animal_call_poke (
ExampleAnimal *proxy,
gboolean arg_make_sad,
gboolean arg_make_happy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);

// 调用方调用完成获取返回结果
gboolean example_animal_call_poke_finish (
ExampleAnimal *proxy,
gboolean *out_result,
GAsyncResult *res,
GError **error);

gboolean example_animal_call_poke_sync (
ExampleAnimal *proxy,
gboolean arg_make_sad,
gboolean arg_make_happy,
gboolean *out_result,
GCancellable *cancellable,
GError **error);

  • 以上代码给出了

    • 接口中定义的信号的发送函数
    • 接口中定义的方法的同步和异步调用函数,以及调用方完成调用函数
    • 接口中定义方法的被调用方完成调用函数example_animal_complete_poke

// 在头文件中
typedef struct
{
  GDBusMethodInfo parent_struct;
  const gchar *signal_name;
  gboolean pass_fdlist;
} _ExtendedGDBusMethodInfo;

// 在源文件中
static const _ExtendedGDBusMethodInfo _example_animal_method_info_poke =
{
{
-1,
(gchar *) "Poke",
(GDBusArgInfo **) &_example_animal_method_info_poke_IN_ARG_pointers,
(GDBusArgInfo **) &_example_animal_method_info_poke_OUT_ARG_pointers,
NULL
},
"handle-poke",
FALSE
};

  • 以上代码给出了XML文件接口中定义的方法的相关信息,"Poke"是定义的方法名,"handle-poke"是为该方法生成的信号名。


  1. gdbus-codegen生成代码

    头文件

    /*
     * This file is generated by gdbus-codegen, do not modify it.
     *
     * The license of this code is the same as for the D-Bus interface description
     * it was derived from. Note that it links to GLib, so must comply with the
     * LGPL linking clauses.
     */
    

    ifndef GENERATED_CODE_H

    define GENERATED_CODE_H

    include <gio/gio.h>

    G_BEGIN_DECLS

    /* ------------------------------------------------------------------------ /
    /
    Declarations for org.gtk.GDBus.Example.ObjectManager.Animal */

    define EXAMPLE_TYPE_ANIMAL (example_animal_get_type ())

    define EXAMPLE_ANIMAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_ANIMAL, ExampleAnimal))

    define EXAMPLE_IS_ANIMAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_ANIMAL))

    define EXAMPLE_ANIMAL_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), EXAMPLE_TYPE_ANIMAL, ExampleAnimalIface))

    struct _ExampleAnimal;
    typedef struct _ExampleAnimal ExampleAnimal;
    typedef struct _ExampleAnimalIface ExampleAnimalIface;

    struct _ExampleAnimalIface
    {
    GTypeInterface parent_iface;

    gboolean (*handle_poke) (
    ExampleAnimal *object,
    GDBusMethodInvocation *invocation,
    gboolean arg_make_sad,
    gboolean arg_make_happy);

    const gchar * (*get_foo) (ExampleAnimal *object);

    const gchar * (*get_mood) (ExampleAnimal *object);

    void (*jumped) (
    ExampleAnimal *object,
    gdouble arg_height);

    const gchar * (*get_bar) (ExampleAnimal *object);

    };

    GType example_animal_get_type (void) G_GNUC_CONST;

    GDBusInterfaceInfo *example_animal_interface_info (void);
    guint example_animal_override_properties (GObjectClass *klass, guint property_id_begin);

    /* D-Bus method call completion functions: */
    void example_animal_complete_poke (
    ExampleAnimal *object,
    GDBusMethodInvocation *invocation,
    gboolean result);

    /* D-Bus signal emissions functions: */
    void example_animal_emit_jumped (
    ExampleAnimal *object,
    gdouble arg_height);

    /* D-Bus method calls: */
    void example_animal_call_poke (
    ExampleAnimal *proxy,
    gboolean arg_make_sad,
    gboolean arg_make_happy,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data);

    gboolean example_animal_call_poke_finish (
    ExampleAnimal *proxy,
    gboolean *out_result,
    GAsyncResult *res,
    GError **error);

    gboolean example_animal_call_poke_sync (
    ExampleAnimal *proxy,
    gboolean arg_make_sad,
    gboolean arg_make_happy,
    gboolean *out_result,
    GCancellable *cancellable,
    GError **error);

    /* D-Bus property accessors: */
    const gchar *example_animal_get_mood (ExampleAnimal *object);
    gchar *example_animal_dup_mood (ExampleAnimal *object);
    void example_animal_set_mood (ExampleAnimal *object, const gchar *value);

    const gchar *example_animal_get_foo (ExampleAnimal *object);
    gchar *example_animal_dup_foo (ExampleAnimal *object);
    void example_animal_set_foo (ExampleAnimal *object, const gchar *value);

    const gchar *example_animal_get_bar (ExampleAnimal *object);
    gchar *example_animal_dup_bar (ExampleAnimal *object);
    void example_animal_set_bar (ExampleAnimal *object, const gchar *value);

    /* ---- */

    define EXAMPLE_TYPE_ANIMAL_PROXY (example_animal_proxy_get_type ())

    define EXAMPLE_ANIMAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_ANIMAL_PROXY, ExampleAnimalProxy))

    define EXAMPLE_ANIMAL_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_ANIMAL_PROXY, ExampleAnimalProxyClass))

    define EXAMPLE_ANIMAL_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_ANIMAL_PROXY, ExampleAnimalProxyClass))

    define EXAMPLE_IS_ANIMAL_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_ANIMAL_PROXY))

    define EXAMPLE_IS_ANIMAL_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_ANIMAL_PROXY))

    typedef struct _ExampleAnimalProxy ExampleAnimalProxy;
    typedef struct _ExampleAnimalProxyClass ExampleAnimalProxyClass;
    typedef struct _ExampleAnimalProxyPrivate ExampleAnimalProxyPrivate;

    struct _ExampleAnimalProxy
    {
    /< private >/
    GDBusProxy parent_instance;
    ExampleAnimalProxyPrivate *priv;
    };

    struct _ExampleAnimalProxyClass
    {
    GDBusProxyClass parent_class;
    };

    GType example_animal_proxy_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleAnimalProxy, g_object_unref)

    endif

    void example_animal_proxy_new (
    GDBusConnection *connection,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data);
    ExampleAnimal *example_animal_proxy_new_finish (
    GAsyncResult *res,
    GError **error);
    ExampleAnimal *example_animal_proxy_new_sync (
    GDBusConnection *connection,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GError **error);

    void example_animal_proxy_new_for_bus (
    GBusType bus_type,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data);
    ExampleAnimal *example_animal_proxy_new_for_bus_finish (
    GAsyncResult *res,
    GError **error);
    ExampleAnimal *example_animal_proxy_new_for_bus_sync (
    GBusType bus_type,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GError **error);

    /* ---- */

    define EXAMPLE_TYPE_ANIMAL_SKELETON (example_animal_skeleton_get_type ())

    define EXAMPLE_ANIMAL_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_ANIMAL_SKELETON, ExampleAnimalSkeleton))

    define EXAMPLE_ANIMAL_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_ANIMAL_SKELETON, ExampleAnimalSkeletonClass))

    define EXAMPLE_ANIMAL_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_ANIMAL_SKELETON, ExampleAnimalSkeletonClass))

    define EXAMPLE_IS_ANIMAL_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_ANIMAL_SKELETON))

    define EXAMPLE_IS_ANIMAL_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_ANIMAL_SKELETON))

    typedef struct _ExampleAnimalSkeleton ExampleAnimalSkeleton;
    typedef struct _ExampleAnimalSkeletonClass ExampleAnimalSkeletonClass;
    typedef struct _ExampleAnimalSkeletonPrivate ExampleAnimalSkeletonPrivate;

    struct _ExampleAnimalSkeleton
    {
    /< private >/
    GDBusInterfaceSkeleton parent_instance;
    ExampleAnimalSkeletonPrivate *priv;
    };

    struct _ExampleAnimalSkeletonClass
    {
    GDBusInterfaceSkeletonClass parent_class;
    };

    GType example_animal_skeleton_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleAnimalSkeleton, g_object_unref)

    endif

    ExampleAnimal *example_animal_skeleton_new (void);

    /* ------------------------------------------------------------------------ /
    /
    Declarations for org.gtk.GDBus.Example.ObjectManager.Cat */

    define EXAMPLE_TYPE_CAT (example_cat_get_type ())

    define EXAMPLE_CAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_CAT, ExampleCat))

    define EXAMPLE_IS_CAT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_CAT))

    define EXAMPLE_CAT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), EXAMPLE_TYPE_CAT, ExampleCatIface))

    struct _ExampleCat;
    typedef struct _ExampleCat ExampleCat;
    typedef struct _ExampleCatIface ExampleCatIface;

    struct _ExampleCatIface
    {
    GTypeInterface parent_iface;
    };

    GType example_cat_get_type (void) G_GNUC_CONST;

    GDBusInterfaceInfo *example_cat_interface_info (void);
    guint example_cat_override_properties (GObjectClass *klass, guint property_id_begin);

    /* ---- */

    define EXAMPLE_TYPE_CAT_PROXY (example_cat_proxy_get_type ())

    define EXAMPLE_CAT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_CAT_PROXY, ExampleCatProxy))

    define EXAMPLE_CAT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_CAT_PROXY, ExampleCatProxyClass))

    define EXAMPLE_CAT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_CAT_PROXY, ExampleCatProxyClass))

    define EXAMPLE_IS_CAT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_CAT_PROXY))

    define EXAMPLE_IS_CAT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_CAT_PROXY))

    typedef struct _ExampleCatProxy ExampleCatProxy;
    typedef struct _ExampleCatProxyClass ExampleCatProxyClass;
    typedef struct _ExampleCatProxyPrivate ExampleCatProxyPrivate;

    struct _ExampleCatProxy
    {
    /< private >/
    GDBusProxy parent_instance;
    ExampleCatProxyPrivate *priv;
    };

    struct _ExampleCatProxyClass
    {
    GDBusProxyClass parent_class;
    };

    GType example_cat_proxy_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleCatProxy, g_object_unref)

    endif

    void example_cat_proxy_new (
    GDBusConnection *connection,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data);
    ExampleCat *example_cat_proxy_new_finish (
    GAsyncResult *res,
    GError **error);
    ExampleCat *example_cat_proxy_new_sync (
    GDBusConnection *connection,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GError **error);

    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);
    ExampleCat *example_cat_proxy_new_for_bus_finish (
    GAsyncResult *res,
    GError **error);
    ExampleCat *example_cat_proxy_new_for_bus_sync (
    GBusType bus_type,
    GDBusProxyFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GError **error);

    /* ---- */

    define EXAMPLE_TYPE_CAT_SKELETON (example_cat_skeleton_get_type ())

    define EXAMPLE_CAT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_CAT_SKELETON, ExampleCatSkeleton))

    define EXAMPLE_CAT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_CAT_SKELETON, ExampleCatSkeletonClass))

    define EXAMPLE_CAT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_CAT_SKELETON, ExampleCatSkeletonClass))

    define EXAMPLE_IS_CAT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_CAT_SKELETON))

    define EXAMPLE_IS_CAT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_CAT_SKELETON))

    typedef struct _ExampleCatSkeleton ExampleCatSkeleton;
    typedef struct _ExampleCatSkeletonClass ExampleCatSkeletonClass;
    typedef struct _ExampleCatSkeletonPrivate ExampleCatSkeletonPrivate;

    struct _ExampleCatSkeleton
    {
    /< private >/
    GDBusInterfaceSkeleton parent_instance;
    ExampleCatSkeletonPrivate *priv;
    };

    struct _ExampleCatSkeletonClass
    {
    GDBusInterfaceSkeletonClass parent_class;
    };

    GType example_cat_skeleton_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleCatSkeleton, g_object_unref)

    endif

    ExampleCat *example_cat_skeleton_new (void);

    /* ---- */

    define EXAMPLE_TYPE_OBJECT (example_object_get_type ())

    define EXAMPLE_OBJECT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_OBJECT, ExampleObject))

    define EXAMPLE_IS_OBJECT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_OBJECT))

    define EXAMPLE_OBJECT_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), EXAMPLE_TYPE_OBJECT, ExampleObject))

    struct _ExampleObject;
    typedef struct _ExampleObject ExampleObject;
    typedef struct _ExampleObjectIface ExampleObjectIface;

    struct _ExampleObjectIface
    {
    GTypeInterface parent_iface;
    };

    GType example_object_get_type (void) G_GNUC_CONST;

    ExampleAnimal *example_object_get_animal (ExampleObject *object);
    ExampleCat *example_object_get_cat (ExampleObject *object);
    ExampleAnimal *example_object_peek_animal (ExampleObject *object);
    ExampleCat *example_object_peek_cat (ExampleObject *object);

    define EXAMPLE_TYPE_OBJECT_PROXY (example_object_proxy_get_type ())

    define EXAMPLE_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_OBJECT_PROXY, ExampleObjectProxy))

    define EXAMPLE_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_OBJECT_PROXY, ExampleObjectProxyClass))

    define EXAMPLE_OBJECT_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_OBJECT_PROXY, ExampleObjectProxyClass))

    define EXAMPLE_IS_OBJECT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_OBJECT_PROXY))

    define EXAMPLE_IS_OBJECT_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_OBJECT_PROXY))

    typedef struct _ExampleObjectProxy ExampleObjectProxy;
    typedef struct _ExampleObjectProxyClass ExampleObjectProxyClass;
    typedef struct _ExampleObjectProxyPrivate ExampleObjectProxyPrivate;

    struct _ExampleObjectProxy
    {
    /< private >/
    GDBusObjectProxy parent_instance;
    ExampleObjectProxyPrivate *priv;
    };

    struct _ExampleObjectProxyClass
    {
    GDBusObjectProxyClass parent_class;
    };

    GType example_object_proxy_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleObjectProxy, g_object_unref)

    endif

    ExampleObjectProxy *example_object_proxy_new (GDBusConnection *connection, const gchar *object_path);

    define EXAMPLE_TYPE_OBJECT_SKELETON (example_object_skeleton_get_type ())

    define EXAMPLE_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_OBJECT_SKELETON, ExampleObjectSkeleton))

    define EXAMPLE_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_OBJECT_SKELETON, ExampleObjectSkeletonClass))

    define EXAMPLE_OBJECT_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_OBJECT_SKELETON, ExampleObjectSkeletonClass))

    define EXAMPLE_IS_OBJECT_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_OBJECT_SKELETON))

    define EXAMPLE_IS_OBJECT_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_OBJECT_SKELETON))

    typedef struct _ExampleObjectSkeleton ExampleObjectSkeleton;
    typedef struct _ExampleObjectSkeletonClass ExampleObjectSkeletonClass;
    typedef struct _ExampleObjectSkeletonPrivate ExampleObjectSkeletonPrivate;

    struct _ExampleObjectSkeleton
    {
    /< private >/
    GDBusObjectSkeleton parent_instance;
    ExampleObjectSkeletonPrivate *priv;
    };

    struct _ExampleObjectSkeletonClass
    {
    GDBusObjectSkeletonClass parent_class;
    };

    GType example_object_skeleton_get_type (void) G_GNUC_CONST;

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleObjectSkeleton, g_object_unref)

    endif

    ExampleObjectSkeleton *example_object_skeleton_new (const gchar *object_path);
    void example_object_skeleton_set_animal (ExampleObjectSkeleton *object, ExampleAnimal *interface_);
    void example_object_skeleton_set_cat (ExampleObjectSkeleton *object, ExampleCat *interface_);

    /* ---- */

    define EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT (example_object_manager_client_get_type ())

    define EXAMPLE_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, ExampleObjectManagerClient))

    define EXAMPLE_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, ExampleObjectManagerClientClass))

    define EXAMPLE_OBJECT_MANAGER_CLIENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT, ExampleObjectManagerClientClass))

    define EXAMPLE_IS_OBJECT_MANAGER_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT))

    define EXAMPLE_IS_OBJECT_MANAGER_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EXAMPLE_TYPE_OBJECT_MANAGER_CLIENT))

    typedef struct _ExampleObjectManagerClient ExampleObjectManagerClient;
    typedef struct _ExampleObjectManagerClientClass ExampleObjectManagerClientClass;
    typedef struct _ExampleObjectManagerClientPrivate ExampleObjectManagerClientPrivate;

    struct _ExampleObjectManagerClient
    {
    /< private >/
    GDBusObjectManagerClient parent_instance;
    ExampleObjectManagerClientPrivate *priv;
    };

    struct _ExampleObjectManagerClientClass
    {
    GDBusObjectManagerClientClass parent_class;
    };

    if GLIB_CHECK_VERSION(2, 44, 0)

    G_DEFINE_AUTOPTR_CLEANUP_FUNC (ExampleObjectManagerClient, g_object_unref)

    endif

    GType example_object_manager_client_get_type (void) G_GNUC_CONST;

    GType example_object_manager_client_get_proxy_type (GDBusObjectManagerClient *manager, const gchar *object_path, const gchar *interface_name, gpointer user_data);

    void example_object_manager_client_new (
    GDBusConnection *connection,
    GDBusObjectManagerClientFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data);
    GDBusObjectManager *example_object_manager_client_new_finish (
    GAsyncResult *res,
    GError **error);
    GDBusObjectManager *example_object_manager_client_new_sync (
    GDBusConnection *connection,
    GDBusObjectManagerClientFlags flags,
    const gchar *name,
    const gchar *object_path,
    GCancellable *cancellable,
    GError **error);

    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);
    GDBusObjectManager *example_object_manager_client_new_for_bus_finish (
    GAsyncResult *res,
    GError **error);
    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);

    G_END_DECLS

    endif /* GENERATED_CODE_H */

    源文件

    /*
     * This file is generated by gdbus-codegen, do not modify it.
     *
     * The license of this code is the same as for the D-Bus interface description
     * it was derived from. Note that it links to GLib, so must comply with the
     * LGPL linking clauses.
     */
    

    ifdef HAVE_CONFIG_H

    include "config.h"

    endif

    include "generated-code.h"

    include <string.h>

    ifdef G_OS_UNIX

    include <gio/gunixfdlist.h>

    endif

    typedef struct
    {
    GDBusArgInfo parent_struct;
    gboolean use_gvariant;
    } _ExtendedGDBusArgInfo;

    typedef struct
    {
    GDBusMethodInfo parent_struct;
    const gchar *signal_name;
    gboolean pass_fdlist;
    } _ExtendedGDBusMethodInfo;

    typedef struct
    {
    GDBusSignalInfo parent_struct;
    const gchar *signal_name;
    } _ExtendedGDBusSignalInfo;

    typedef struct
    {
    GDBusPropertyInfo parent_struct;
    const gchar *hyphen_name;
    guint use_gvariant : 1;
    guint emits_changed_signal : 1;
    } _ExtendedGDBusPropertyInfo;

    typedef struct
    {
    GDBusInterfaceInfo parent_struct;
    const gchar *hyphen_name;
    } _ExtendedGDBusInterfaceInfo;

    typedef struct
    {
    const _ExtendedGDBusPropertyInfo info;
    guint prop_id;
    GValue orig_value; /
    the value before the change */
    } ChangedProperty;

    static void
    _changed_property_free (ChangedProperty *data)
    {
    g_value_unset (&data->orig_value);
    g_free (data);
    }

    static gboolean
    _g_strv_equal0 (gchar **a, gchar **b)
    {
    gboolean ret = FALSE;
    guint n;
    if (a == NULL && b == NULL)
    {
    ret = TRUE;
    goto out;
    }
    if (a == NULL || b == NULL)
    goto out;
    if (g_strv_length (a) != g_strv_length (b))
    goto out;
    for (n = 0; a[n] != NULL; n++)
    if (g_strcmp0 (a[n], b[n]) != 0)
    goto out;
    ret = TRUE;
    out:
    return ret;
    }

    static gboolean
    _g_variant_equal0 (GVariant *a, GVariant *b)
    {
    gboolean ret = FALSE;
    if (a == NULL && b == NULL)
    {
    ret = TRUE;
    goto out;
    }
    if (a == NULL || b == NULL)
    goto out;
    ret = g_variant_equal (a, b);
    out:
    return ret;
    }

    G_GNUC_UNUSED static gboolean
    _g_value_equal (const GValue *a, const GValue b)
    {
    gboolean ret = FALSE;
    g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
    switch (G_VALUE_TYPE (a))
    {
    case G_TYPE_BOOLEAN:
    ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
    break;
    case G_TYPE_UCHAR:
    ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
    break;
    case G_TYPE_INT:
    ret = (g_value_get_int (a) == g_value_get_int (b));
    break;
    case G_TYPE_UINT:
    ret = (g_value_get_uint (a) == g_value_get_uint (b));
    break;
    case G_TYPE_INT64:
    ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
    break;
    case G_TYPE_UINT64:
    ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
    break;
    case G_TYPE_DOUBLE:
    {
    /
    Avoid -Wfloat-equal warnings by doing a direct bit compare */
    gdouble da = g_value_get_double (a);
    gdouble db = g_value_get_double (b);
    ret = memcmp (&da, &db, sizeof (gdouble)) == 0;
    }
    break;
    case G_TYPE_STRING:
    ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
    break;
    case G_TYPE_VARIANT:
    ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));
    break;
    default:
    if (G_VALUE_TYPE (a) == G_TYPE_STRV)
    ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));
    else
    g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));
    break;
    }
    return ret;
    }

    /* ------------------------------------------------------------------------

    • Code for interface org.gtk.GDBus.Example.ObjectManager.Animal

    */

    /**

    • SECTION:ExampleAnimal
    • @title: ExampleAnimal
    • @short_description: Generated C code for the org.gtk.GDBus.Example.ObjectManager.Animal D-Bus interface
    • This section contains code for working with the <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link> D-Bus interface in C.
      */

    /* ---- Introspection data for org.gtk.GDBus.Example.ObjectManager.Animal ---- */

    static const _ExtendedGDBusArgInfo _example_animal_method_info_poke_IN_ARG_make_sad =
    {
    {
    -1,
    (gchar *) "make_sad",
    (gchar *) "b",
    NULL
    },
    FALSE
    };

    static const _ExtendedGDBusArgInfo _example_animal_method_info_poke_IN_ARG_make_happy =
    {
    {
    -1,
    (gchar *) "make_happy",
    (gchar *) "b",
    NULL
    },
    FALSE
    };

    static const GDBusArgInfo * const _example_animal_method_info_poke_IN_ARG_pointers[] =
    {
    &_example_animal_method_info_poke_IN_ARG_make_sad.parent_struct,
    &_example_animal_method_info_poke_IN_ARG_make_happy.parent_struct,
    NULL
    };

    static const _ExtendedGDBusArgInfo _example_animal_method_info_poke_OUT_ARG_result =
    {
    {
    -1,
    (gchar *) "result",
    (gchar *) "b",
    NULL
    },
    FALSE
    };

    static const GDBusArgInfo * const _example_animal_method_info_poke_OUT_ARG_pointers[] =
    {
    &_example_animal_method_info_poke_OUT_ARG_result.parent_struct,
    NULL
    };

    static const _ExtendedGDBusMethodInfo _example_animal_method_info_poke =
    {
    {
    -1,
    (gchar *) "Poke",
    (GDBusArgInfo **) &_example_animal_method_info_poke_IN_ARG_pointers,
    (GDBusArgInfo **) &_example_animal_method_info_poke_OUT_ARG_pointers,
    NULL
    },
    "handle-poke",
    FALSE
    };

    static const GDBusMethodInfo * const _example_animal_method_info_pointers[] =
    {
    &_example_animal_method_info_poke.parent_struct,
    NULL
    };

    static const _ExtendedGDBusArgInfo _example_animal_signal_info_jumped_ARG_height =
    {
    {
    -1,
    (gchar *) "height",
    (gchar *) "d",
    NULL
    },
    FALSE
    };

    static const GDBusArgInfo * const _example_animal_signal_info_jumped_ARG_pointers[] =
    {
    &_example_animal_signal_info_jumped_ARG_height.parent_struct,
    NULL
    };

    static const _ExtendedGDBusSignalInfo _example_animal_signal_info_jumped =
    {
    {
    -1,
    (gchar *) "Jumped",
    (GDBusArgInfo **) &_example_animal_signal_info_jumped_ARG_pointers,
    NULL
    },
    "jumped"
    };

    static const GDBusSignalInfo * const _example_animal_signal_info_pointers[] =
    {
    &_example_animal_signal_info_jumped.parent_struct,
    NULL
    };

    static const _ExtendedGDBusPropertyInfo _example_animal_property_info_mood =
    {
    {
    -1,
    (gchar *) "Mood",
    (gchar *) "s",
    G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
    NULL
    },
    "mood",
    FALSE,
    TRUE
    };

    static const _ExtendedGDBusPropertyInfo _example_animal_property_info_foo =
    {
    {
    -1,
    (gchar *) "Foo",
    (gchar *) "s",
    G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
    NULL
    },
    "foo",
    FALSE,
    TRUE
    };

    static const _ExtendedGDBusPropertyInfo _example_animal_property_info_bar =
    {
    {
    -1,
    (gchar *) "Bar",
    (gchar *) "s",
    G_DBUS_PROPERTY_INFO_FLAGS_READABLE,
    NULL
    },
    "bar",
    FALSE,
    TRUE
    };

    static const GDBusPropertyInfo * const _example_animal_property_info_pointers[] =
    {
    &_example_animal_property_info_mood.parent_struct,
    &_example_animal_property_info_foo.parent_struct,
    &_example_animal_property_info_bar.parent_struct,
    NULL
    };

    static const _ExtendedGDBusInterfaceInfo _example_animal_interface_info =
    {
    {
    -1,
    (gchar *) "org.gtk.GDBus.Example.ObjectManager.Animal",
    (GDBusMethodInfo **) &_example_animal_method_info_pointers,
    (GDBusSignalInfo **) &_example_animal_signal_info_pointers,
    (GDBusPropertyInfo **) &_example_animal_property_info_pointers,
    NULL
    },
    "animal",
    };

    /**

    • example_animal_interface_info:
    • Gets a machine-readable description of the <link linkend="gdbus-interface-org-gtk-GDBus-Example-ObjectManager-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link> D-Bus interface.
    • Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
    • Since: 2.30
      */
      GDBusInterfaceInfo *
      example_animal_interface_info (void)
      {
      return (GDBusInterfaceInfo *) &_example_animal_interface_info.parent_struct;
      }

    /**

    • example_animal_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 #ExampleAnimal interface for a concrete class.
    • The properties are overridden in the order they are defined.
    • Returns: The last property id.
    • Since: 2.30
      */
      guint
      example_animal_override_properties (GObjectClass *klass, guint property_id_begin)
      {
      g_object_class_override_property (klass, property_id_begin++, "mood");
      g_object_class_override_property (klass, property_id_begin++, "foo");
      g_object_class_override_property (klass, property_id_begin++, "bar");
      return property_id_begin - 1;
      }

    /**

    • ExampleAnimal:
    • Abstract interface type 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>.
    • Since: 2.30
      */

    /**

    • ExampleAnimalIface:
    • @parent_iface: The parent interface.
    • @handle_poke: Handler for the #ExampleAnimal::handle-poke signal.
    • @get_foo: Getter for the #ExampleAnimal:foo property.
    • @get_mood: Getter for the #ExampleAnimal:mood property.
    • @jumped: Handler for the #ExampleAnimal::jumped signal.
    • @get_bar: Getter for the #ExampleAnimal:bar property.
    • Virtual table 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>.
    • Since: 2.30
      */

    typedef ExampleAnimalIface ExampleAnimalInterface;
    G_DEFINE_INTERFACE (ExampleAnimal, example_animal, G_TYPE_OBJECT)

    static void
    example_animal_default_init (ExampleAnimalIface iface)
    {
    /
    GObject signals for incoming D-Bus method calls: /
    /
    *

    • ExampleAnimal::handle-poke:
    • @object: A #ExampleAnimal.
    • @invocation: A #GDBusMethodInvocation.
    • @arg_make_sad: Argument passed by remote caller.
    • @arg_make_happy: Argument passed by remote caller.
    • Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-org-gtk-GDBus-Example-ObjectManager-Animal.Poke">Poke()</link> D-Bus method.
    • If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call example_animal_complete_poke() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
    • Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
    • Since: 2.30
      */
      g_signal_new ("handle-poke",
      G_TYPE_FROM_INTERFACE (iface),
      G_SIGNAL_RUN_LAST,
      G_STRUCT_OFFSET (ExampleAnimalIface, handle_poke),
      g_signal_accumulator_true_handled,
      NULL,
      g_cclosure_marshal_generic,
      G_TYPE_BOOLEAN,
      3,
      G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);

    /* GObject signals for received D-Bus signals: /
    /
    *

    • ExampleAnimal::jumped:
    • @object: A #ExampleAnimal.
    • @arg_height: Argument.
    • On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-org-gtk-GDBus-Example-ObjectManager-Animal.Jumped">"Jumped"</link> is received.
    • On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
    • Since: 2.30
      */
      g_signal_new ("jumped",
      G_TYPE_FROM_INTERFACE (iface),
      G_SIGNAL_RUN_LAST,
      G_STRUCT_OFFSET (ExampleAnimalIface, jumped),
      NULL,
      NULL,
      g_cclosure_marshal_generic,
      G_TYPE_NONE,
      1, G_TYPE_DOUBLE);

    /* GObject properties for D-Bus properties: /
    /
    *

    • ExampleAnimal:mood:
    • Represents the D-Bus property <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Mood">"Mood"</link>.
    • Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side.
    • Since: 2.30
      /
      g_object_interface_install_property (iface,
      g_param_spec_string ("mood", "Mood", "Mood", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      /
      *
    • ExampleAnimal:foo:
    • Represents the D-Bus property <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Foo">"Foo"</link>.
    • Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side.
    • Since: 2.30
      /
      g_object_interface_install_property (iface,
      g_param_spec_string ("foo", "Foo", "Foo", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      /
      *
    • ExampleAnimal:bar:
    • Represents the D-Bus property <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Bar">"Bar"</link>.
    • Since the D-Bus property for this #GObject property is readable but not writable, it is meaningful to read from it on both the client- and service-side. It is only meaningful, however, to write to it on the service-side.
    • Since: 2.36
      */
      g_object_interface_install_property (iface,
      g_param_spec_string ("bar", "Bar", "Bar", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
      }

    /**

    • example_animal_get_mood: (skip)
    • @object: A #ExampleAnimal.
    • Gets the value of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Mood">"Mood"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use example_animal_dup_mood() if on another thread.
    • Returns: (transfer none) (nullable): The property value or %NULL if the property is not set. Do not free the returned value, it belongs to @object.
    • Since: 2.30
      */
      const gchar *
      example_animal_get_mood (ExampleAnimal *object)
      {
      return EXAMPLE_ANIMAL_GET_IFACE (object)->get_mood (object);
      }

    /**

    • example_animal_dup_mood: (skip)
    • @object: A #ExampleAnimal.
    • Gets a copy of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Mood">"Mood"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • Returns: (transfer full) (nullable): The property value or %NULL if the property is not set. The returned value should be freed with g_free().
    • Since: 2.30
      */
      gchar *
      example_animal_dup_mood (ExampleAnimal *object)
      {
      gchar *value;
      g_object_get (G_OBJECT (object), "mood", &value, NULL);
      return value;
      }

    /**

    • example_animal_set_mood: (skip)
    • @object: A #ExampleAnimal.
    • @value: The value to set.
    • Sets the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Mood">"Mood"</link> D-Bus property to @value.
    • Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side.
    • Since: 2.30
      */
      void
      example_animal_set_mood (ExampleAnimal *object, const gchar *value)
      {
      g_object_set (G_OBJECT (object), "mood", value, NULL);
      }

    /**

    • example_animal_get_foo: (skip)
    • @object: A #ExampleAnimal.
    • Gets the value of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Foo">"Foo"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use example_animal_dup_foo() if on another thread.
    • Returns: (transfer none) (nullable): The property value or %NULL if the property is not set. Do not free the returned value, it belongs to @object.
    • Since: 2.30
      */
      const gchar *
      example_animal_get_foo (ExampleAnimal *object)
      {
      return EXAMPLE_ANIMAL_GET_IFACE (object)->get_foo (object);
      }

    /**

    • example_animal_dup_foo: (skip)
    • @object: A #ExampleAnimal.
    • Gets a copy of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Foo">"Foo"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • Returns: (transfer full) (nullable): The property value or %NULL if the property is not set. The returned value should be freed with g_free().
    • Since: 2.30
      */
      gchar *
      example_animal_dup_foo (ExampleAnimal *object)
      {
      gchar *value;
      g_object_get (G_OBJECT (object), "foo", &value, NULL);
      return value;
      }

    /**

    • example_animal_set_foo: (skip)
    • @object: A #ExampleAnimal.
    • @value: The value to set.
    • Sets the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Foo">"Foo"</link> D-Bus property to @value.
    • Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side.
    • Since: 2.30
      */
      void
      example_animal_set_foo (ExampleAnimal *object, const gchar *value)
      {
      g_object_set (G_OBJECT (object), "foo", value, NULL);
      }

    /**

    • example_animal_get_bar: (skip)
    • @object: A #ExampleAnimal.
    • Gets the value of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Bar">"Bar"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • The returned value is only valid until the property changes so on the client-side it is only safe to use this function on the thread where @object was constructed. Use example_animal_dup_bar() if on another thread.
    • Returns: (transfer none) (nullable): The property value or %NULL if the property is not set. Do not free the returned value, it belongs to @object.
    • Since: 2.36
      */
      const gchar *
      example_animal_get_bar (ExampleAnimal *object)
      {
      return EXAMPLE_ANIMAL_GET_IFACE (object)->get_bar (object);
      }

    /**

    • example_animal_dup_bar: (skip)
    • @object: A #ExampleAnimal.
    • Gets a copy of the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Bar">"Bar"</link> D-Bus property.
    • Since this D-Bus property is readable, it is meaningful to use this function on both the client- and service-side.
    • Returns: (transfer full) (nullable): The property value or %NULL if the property is not set. The returned value should be freed with g_free().
    • Since: 2.36
      */
      gchar *
      example_animal_dup_bar (ExampleAnimal *object)
      {
      gchar *value;
      g_object_get (G_OBJECT (object), "bar", &value, NULL);
      return value;
      }

    /**

    • example_animal_set_bar: (skip)
    • @object: A #ExampleAnimal.
    • @value: The value to set.
    • Sets the <link linkend="gdbus-property-org-gtk-GDBus-Example-ObjectManager-Animal.Bar">"Bar"</link> D-Bus property to @value.
    • Since this D-Bus property is not writable, it is only meaningful to use this function on the service-side.
    • Since: 2.36
      */
      void
      example_animal_set_bar (ExampleAnimal *object, const gchar *value)
      {
      g_object_set (G_OBJECT (object), "bar", value, NULL);
      }

    /**

    • example_animal_emit_jumped:
    • @object: A #ExampleAnimal.
    • @arg_height: Argument to pass with the signal.
    • Emits the <link linkend="gdbus-signal-org-gtk-GDBus-Example-ObjectManager-Animal.Jumped">"Jumped"</link> D-Bus signal.
    • Since: 2.30
      */
      void
      example_animal_emit_jumped (
      ExampleAnimal *object,
      gdouble arg_height)
      {
      g_signal_emit_by_name (object, "jumped", arg_height);
      }

    /**

    • example_animal_call_poke:
    • @proxy: A #ExampleAnimalProxy.
    • @arg_make_sad: Argument to pass with the method invocation.
    • @arg_make_happy: Argument to pass with the method invocation.
    • @cancellable: (nullable): A #GCancellable or %NULL.
    • @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
    • @user_data: User data to pass to @callback.
    • Asynchronously invokes the <link linkend="gdbus-method-org-gtk-GDBus-Example-ObjectManager-Animal.Poke">Poke()</link> D-Bus method on @proxy.
    • 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_animal_call_poke_finish() to get the result of the operation.
    • See example_animal_call_poke_sync() for the synchronous, blocking version of this method.
    • Since: 2.30
      */
      void
      example_animal_call_poke (
      ExampleAnimal *proxy,
      gboolean arg_make_sad,
      gboolean arg_make_happy,
      GCancellable *cancellable,
      GAsyncReadyCallback callback,
      gpointer user_data)
      {
      g_dbus_proxy_call (G_DBUS_PROXY (proxy),
      "Poke",
      g_variant_new ("(bb)",
      arg_make_sad,
      arg_make_happy),
      G_DBUS_CALL_FLAGS_NONE,
      -1,
      cancellable,
      callback,
      user_data);
      }

    /**

    • example_animal_call_poke_finish:
    • @proxy: A #ExampleAnimalProxy.
    • @out_result: (out) (optional): Return location for return parameter or %NULL to ignore.
    • @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_animal_call_poke().
    • @error: Return location for error or %NULL.
    • Finishes an operation started with example_animal_call_poke().
    • Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
    • Since: 2.30
      */
      gboolean
      example_animal_call_poke_finish (
      ExampleAnimal *proxy,
      gboolean *out_result,
      GAsyncResult *res,
      GError **error)
      {
      GVariant *_ret;
      _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
      if (_ret == NULL)
      goto _out;
      g_variant_get (_ret,
      "(b)",
      out_result);
      g_variant_unref (_ret);
      _out:
      return _ret != NULL;
      }

    /**

    • example_animal_call_poke_sync:
    • @proxy: A #ExampleAnimalProxy.
    • @arg_make_sad: Argument to pass with the method invocation.
    • @arg_make_happy: Argument to pass with the method invocation.
    • @out_result: (out) (optional): Return location for return parameter or %NULL to ignore.
    • @cancellable: (nullable): A #GCancellable or %NULL.
    • @error: Return location for error or %NULL.
    • Synchronously invokes the <link linkend="gdbus-method-org-gtk-GDBus-Example-ObjectManager-Animal.Poke">Poke()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
    • See example_animal_call_poke() for the asynchronous version of this method.
    • Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
    • Since: 2.30
      */
      gboolean
      example_animal_call_poke_sync (
      ExampleAnimal *proxy,
      gboolean arg_make_sad,
      gboolean arg_make_happy,
      gboolean *out_result,
      GCancellable *cancellable,
      GError **error)
      {
      GVariant *_ret;
      _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
      "Poke",
      g_variant_new ("(bb)",
      arg_make_sad,
      arg_make_happy),
      G_DBUS_CALL_FLAGS_NONE,
      -1,
      cancellable,
      error);
      if (_ret == NULL)
      goto _out;
      g_variant_get (_ret,
      "(b)",
      out_result);
      g_variant_unref (_ret);
      _out:
      return _ret != NULL;
      }

    /**

    • example_animal_complete_poke:
    • @object: A #ExampleAnimal.
    • @invocation: (transfer full): A #GDBusMethodInvocation.
    • @result: Parameter to return.
    • Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-org-gtk-GDBus-Example-ObjectManager-Animal.Poke">Poke()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
    • This method will free @invocation, you cannot use it afterwards.
    • Since: 2.30
      */
      void
      example_animal_complete_poke (
      ExampleAnimal *object,
      GDBusMethodInvocation *invocation,
      gboolean result)
      {
      g_dbus_method_invocation_return_value (invocation,
      g_variant_new ("(b)",
      result));
      }

    /* ------------------------------------------------------------------------ */

    /**

    • ExampleAnimalProxy:
    • The #ExampleAnimalProxy structure contains only private data and should only be accessed using the provided API.
    • Since: 2.30
      */

    /**

    • ExampleAnimalProxyClass:
    • @parent_class: The parent class.
    • Class structure for #ExampleAnimalProxy.
    • Since: 2.30
      */

    struct _ExampleAnimalProxyPrivate
    {
    GData *qdata;
    };

    static void example_animal_proxy_iface_init (ExampleAnimalIface *iface);

    if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38

    G_DEFINE_TYPE_WITH_CODE (ExampleAnimalProxy, example_animal_proxy, G_TYPE_DBUS_PROXY,
    G_ADD_PRIVATE (ExampleAnimalProxy)
    G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_ANIMAL, example_animal_proxy_iface_init))

    else

    G_DEFINE_TYPE_WITH_CODE (ExampleAnimalProxy, example_animal_proxy, G_TYPE_DBUS_PROXY,
    G_IMPLEMENT_INTERFACE (EXAMPLE_TYPE_ANIMAL, example_animal_proxy_iface_init))

    endif

    static void
    example_animal_proxy_finalize (GObject *object)
    {
    ExampleAnimalProxy *proxy = EXAMPLE_ANIMAL_PROXY (object);
    g_datalist_clear (&proxy->priv->qdata);
    G_OBJECT_CLASS (example_animal_proxy_parent_class)->finalize (object);
    }

    static void
    example_animal_proxy_get_property (GObject *object,
    guint prop_id,
    GValue *value,
    GParamSpec *pspec G_GNUC_UNUSED)
    {
    const _ExtendedGDBusPropertyInfo *info;
    GVariant *variant;
    g_assert (prop_id != 0 && prop_id - 1 < 3);
    info = (const _ExtendedGDBusPropertyInfo *) _example_animal_property_info_pointers[prop_id - 1];
    variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (object), info->parent_struct.name);
    if (info->use_gvariant)
    {
    g_value_set_variant (value, variant);
    }
    else
    {
    if (variant != NULL)
    g_dbus_gvariant_to_gvalue (variant, value);
    }
    if (variant != NULL)
    g_variant_unref (variant);
    }

    static void
    example_animal_proxy_set_property_cb (GDBusProxy *proxy,
    GAsyncResult *res,
    gpointer user_data)
    {
    const _ExtendedGDBusPropertyInfo *info = user_data;
    GError *error;
    GVariant *_ret;
    error = NULL;
    _ret = g_dbus_proxy_call_finish (proxy, res, &error);
    if (!_ret)
    {
    g_warning ("Error setting property '%s' on interface org.gtk.GDBus.Example.ObjectManager.Animal: %s (%s, %d)",
    info->parent_struct.name,
    error->message, g_quark_to_string (error->domain), error->code);
    g_error_free (error);
    }
    else
    {
    g_variant_unref (_ret);
    }
    }

    static void
    example_animal_proxy_set_property (GObject *object,
    guint prop_id,
    const GValue *value,
    GParamSpec *pspec G_GNUC_UNUSED)
    {
    const _ExtendedGDBusPropertyInfo *info;
    GVariant *variant;
    g_assert (prop_id != 0 && prop_id - 1 < 3);
    info = (const _ExtendedGDBusPropertyInfo *) _example_animal_property_info_pointers[prop_id - 1];
    variant = g_dbus_gvalue_to_gvariant (value, G_VARIANT_TYPE (info->parent_struct.signature));
    g_dbus_proxy_call (G_DBUS_PROXY (object),
    "org.freedesktop.DBus.Properties.Set",
    g_variant_new ("(ssv)", "org.gtk.GDBus.Example.ObjectManager.Animal", info->parent_struct.name, variant),
    G_DBUS_CALL_FLAGS_NONE,
    -1,
    NULL, (GAsyncReadyCallback) example_animal_proxy_set_property_cb, (GDBusPropertyInfo *) &info->parent_struct);
    g_variant_unref (variant);
    }

    static void
    example_animal_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_animal_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_ANIMAL);
    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_ANIMAL);
    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_animal_proxy_g_properties_changed (GDBusProxy *_proxy,
    GVariant *changed_properties,
    const gchar *const *invalidated_properties)
    {
    ExampleAnimalProxy *proxy = EXAMPLE_ANIMAL_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_animal_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_animal_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 const gchar *
    example_animal_proxy_get_mood (ExampleAnimal *object)
    {
    ExampleAnimalProxy *proxy = EXAMPLE_ANIMAL_PROXY (object);
    GVariant *variant;
    const gchar *value = NULL;
    variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Mood");
    if (variant != NULL)
    {
    value = g_variant_get_string (variant, NULL);
    g_variant_unref (variant);
    }
    return value;
    }

    static const gchar *
    example_animal_proxy_get_foo (ExampleAnimal *object)
    {
    ExampleAnimalProxy *proxy = EXAMPLE_ANIMAL_PROXY (object);
    GVariant *variant;
    const gchar *value = NULL;
    variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Foo");
    if (variant != NULL)
    {
    value = g_variant_get_string (variant, NULL);
    g_variant_unref (variant);
    }
    return value;
    }

    static const gchar *
    example_animal_proxy_get_bar (ExampleAnimal *object)
    {
    ExampleAnimalProxy *proxy = EXAMPLE_ANIMAL_PROXY (object);
    GVariant *variant;
    const gchar *value = NULL;
    variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Bar");
    if (variant != NULL)
    {
    value = g_variant_get_string (variant, NULL);
    g_variant_unref (variant);
    }
    return value;
    }

    static void
    example_animal_proxy_init (ExampleAnimalProxy *proxy)
    {

    if GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38

    proxy->priv = example_animal_proxy_get_instance_private (proxy);

    else

    proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, EXAMPLE_TYPE_ANIMAL_PROXY, ExampleAnimalProxyPrivate);

    endif

    g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), example_animal_interface_info ());
    }

    static void
    example_animal_proxy_class_init (ExampleAnimalProxyClass *klass)
    {
    GObjectClass *gobject_class;
    GDBusProxyClass *proxy_class;

    gobject_class = G_OBJECT_CLASS (klass);
    gobject_class->finalize = example_animal_proxy_finalize;
    gobject_class->get_property = example_animal_proxy_get_property;
    gobject_class->set_property = example_animal_proxy_set_property;

    proxy_class = G_DBUS_PROXY_CLASS (klass);
    proxy_class->g_signal = example_animal_proxy_g_signal;
    proxy_class->g_properties_changed = example_animal_proxy_g_properties_changed;

    example_animal_override_properties (gobject_class, 1);

    if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_38

    g_type_class_add_private (klass, sizeof (ExampleAnimalProxyPrivate));

    endif

    }

    static void
    example_animal_proxy_iface_init (ExampleAnimalIface *iface)
    {
    iface->get_mood = example_animal_proxy_get_mood;
    iface->get_foo = example_animal_proxy_get_foo;
    iface->get_bar = example_animal_proxy_get_bar;
    }

    /**

    • example_animal_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-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</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_animal_proxy_new_finish() to get the result of the operation.
    • See example_animal_proxy_new_sync() for the synchronous, blocking version of this constructor.
    • Since: 2.30
      */
      void
      example_animal_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_ANIMAL_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.Animal", NULL);
      }

    /**

    • example_animal_proxy_new_finish:
    • @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_animal_proxy_new().
    • @error: Return location for error or %NULL
    • Finishes an operation started with example_animal_proxy_new().
    • Returns: (transfer full) (type ExampleAnimalProxy): The constructed proxy object or %NULL if @error is set.
    • Since: 2.30
      */
      ExampleAnimal *
      example_animal_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_ANIMAL (ret);
      else
      return NULL;
      }

    /**

    • example_animal_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-Animal.top_of_page">org.gtk.GDBus.Example.ObjectManager.Animal</link>. See g_dbus_proxy_new_sync() for more details.
    • The calling thread is blocked until a reply is received.
    • See example_animal_proxy_new() for the asynchronous version of this constructor.
    • Returns: (transfer full) (type ExampleAnimalProxy): The constructed proxy object or %NULL if @error is set.
    • Since: 2.30
      */
      ExampleAnimal *
      example_animal_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_ANIMAL_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.Animal", NULL);
      if (ret != NULL)
      return EXAMPLE_ANIMAL (ret);
      else
      return NULL;
      }

    /**

    • example_animal_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_animal_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_animal_proxy_new_for_bus_finish() to get the result of the operation.
    • See example_animal_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
    • Since: 2.30
      */
      void
      example_animal_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_ANIMAL_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.Animal", NULL);
      }

    /**

    • example_animal_proxy_new_for_bus_finish:
    • @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to example_animal_proxy_new_for_bus().
    • @error: Return location for error or %NULL
    • Finishes an operation started with example_animal_proxy_new_for_bus().
    • Returns: (transfer full) (type ExampleAnimalProxy): The constructed proxy object or %NULL if @error is set.
    • Since: 2.30
      */
      ExampleAnimal *
      example_animal_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_ANIMAL (ret);
      else
      return NULL;
      }

    /**

    • example_animal_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_animal_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
    • The calling thread is blocked until a reply is received.
    • See example_animal_proxy_new_for_bus() for the asynchronous version of this constructor.
    • Returns: (transfer full) (type ExampleAnimalProxy): The constructed proxy object or %NULL if @error is set.
    • Since: 2.30
      */
      ExampleAnimal *
      example_animal_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_ANIMAL_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.Animal", NULL);
      if (ret != NULL)
      return EXAMPLE_ANIMAL (ret);
      else
      return NULL;
      }

    /* ------------------------------------------------------------------------ */

    /**

    • ExampleAnimalSkeleton:
    • The #ExampleAnimalSkeleton structure contains only private data and should only be accessed using the provided API.
    • Since: 2.30
      */

    /**

    • ExampleAnimalSkeletonClass:
    • @parent_class: The parent class.
    • Class structure for #ExampleAnimalSkeleton.
    • Since: 2.30
      */

    struct _ExampleAnimalSkeletonPrivate
    {
    GValue *properties;
    GList *changed_properties;
    GSource *changed_properties_idle_source;
    GMainContext *context;
    GMutex lock;
    };

    static void
    _example_animal_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)
    {
    ExampleAnimalSkeleton *skeleton = EXAMPLE_ANIMAL_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_ANIMAL);
    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

      g_value_init (&amp;paramv[n], G_TYPE_UNIX_FD_LIST);
      g_value_set_object (&amp;paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
    

    else

      g_assert_not_reached ();
    

    endif

    }
    

    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;

      cur_value = &amp;skeleton-&gt;priv-&gt;properties[cp-&gt;prop_id - 1];
      if (!_g_value_equal (cur_value, &amp;cp-&gt;orig_value))
        {
          variant = g_dbus_gvalue_to_gvariant (cur_value, G_VARIANT_TYPE (cp-&gt;info-&gt;parent_struct.signature));
          g_variant_builder_add (&amp;builder, &quot;{sv}&quot;, cp-&gt;info-&gt;parent_struct.name, variant);
          g_variant_unref (variant);
          num_changes++;
        }
    }
    

    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;

          g_dbus_connection_emit_signal (connection,
                                         NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)),
                                         &quot;org.freedesktop.DBus.Properties&quot;,
                                         &quot;PropertiesChanged&quot;,
                                         signal_variant,
                                         NULL);
        }
      g_variant_unref (signal_variant);
      g_list_free_full (connections, g_object_unref);
    }
    

    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

      g_value_init (&amp;paramv[n], G_TYPE_UNIX_FD_LIST);
      g_value_set_object (&amp;paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
    

    else

      g_assert_not_reached ();
    

    endif

    }
    

    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;

    case 2:
      interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), &quot;org.gtk.GDBus.Example.ObjectManager.Cat&quot;);
      g_value_take_object (value, interface);
      break;
    
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    

    }
    }

    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;

    case 2:
      interface = g_value_get_object (value);
      if (interface != NULL)
        {
          g_warn_if_fail (EXAMPLE_IS_CAT (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), &quot;org.gtk.GDBus.Example.ObjectManager.Cat&quot;);
        }
      break;
    
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    

    }
    }

    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;

    case 2:
      interface = g_dbus_object_get_interface (G_DBUS_OBJECT (object), &quot;org.gtk.GDBus.Example.ObjectManager.Cat&quot;);
      g_value_take_object (value, interface);
      break;
    
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
      break;
    

    }
    }

    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;
      }


posted @ 2025-08-03 21:07  重光拾  阅读(57)  评论(0)    收藏  举报