当前位置: 首页 > news >正文

使用GLib D-Bus 库创建dbus服务端

结合:使用GLib D-Bus 库创建dbus客户端-CSDN博客

函数g_dbus_node_info_new_for_xml的用法

g_dbus_node_info_new_for_xml 是 GLib 中用于解析 D-Bus 接口描述 XML 并生成 GDBusNodeInfo 对象的函数,其核心功能是将 XML 格式的接口定义转换为程序可操作的结构化数据。以下是详细用法说明:


函数原型

GDBusNodeInfo *g_dbus_node_info_new_for_xml (const gchar *xml_data, GError **error);

参数说明

  1. xml_data

    • 类型:const gchar*
    • 作用:传入符合 D-Bus 接口描述的 XML 字符串。
    • 格式要求:需包含完整的 <node> 和 <interface> 定义,例如:
      <node><interface name="org.example.MyInterface"><method name="ExampleMethod"><arg type="s" name="input" direction="in"/><arg type="i" name="output" direction="out"/></method></interface>
      </node>
      
  2. error

    • 类型:GError**
    • 作用:捕获解析过程中的错误(如 XML 格式无效或接口定义冲突)。
    • 若解析失败,函数返回 NULL 并通过此参数返回错误详情。

返回值

  • 成功时返回 GDBusNodeInfo* 对象,包含解析后的接口、方法、信号和属性信息。
  • 需通过 g_dbus_node_info_unref() 释放内存以避免泄漏。

典型用法示例

  1. 定义 XML 接口描述
    静态字符串或从文件加载均可:

    static const gchar introspection_xml[] ="<node>""  <interface name='org.example.Test'>""    <method name='Echo'>""      <arg type='s' name='input' direction='in'/>""      <arg type='s' name='output' direction='out'/>""    </method>""  </interface>""</node>";
    
  2. 解析并注册接口

    GError *error = NULL;
    GDBusNodeInfo *info = g_dbus_node_info_new_for_xml(introspection_xml, &error);
    if (info == NULL) {g_printerr("解析失败: %s\n", error->message);g_error_free(error);return;
    }
    
  3. 使用解析结果

    • 通过 info->interfaces 访问接口列表。
    • 结合 g_dbus_connection_register_object() 将接口注册到 D-Bus 总线上。

注意事项

  • 线程安全‌:需在 GLib 主循环线程中调用。
  • XML 校验‌:需确保 XML 符合 D-Bus 规范,否则可能返回错误。
  • 生命周期管理‌:返回的 GDBusNodeInfo 对象需手动释放。

函数g_dbus_node_info_lookup_interface的用法

g_dbus_node_info_lookup_interface 是 GLib 中用于从已解析的 D-Bus 节点信息中查找特定接口的函数,其核心功能是通过接口名称快速定位接口定义。以下是详细说明:


函数原型

GDBusInterfaceInfo *g_dbus_node_info_lookup_interface (GDBusNodeInfo *info,const gchar *interface_name
);

参数说明

  1. info

    • 类型:GDBusNodeInfo*
    • 作用:指向通过 g_dbus_node_info_new_for_xml 解析得到的节点信息对象。
    • 要求:必须为非 NULL 的有效对象,否则行为未定义。
  2. interface_name

    • 类型:const gchar*
    • 作用:需查找的接口名称(如 "org.example.MyInterface")。
    • 注意:名称需与 XML 定义中的接口名完全匹配(区分大小写)。

返回值

  • 成功‌:返回指向 GDBusInterfaceInfo 的指针,包含接口的方法、信号和属性定义。
  • 失败‌:若未找到匹配接口,返回 NULL
  • 注意:返回的指针为内部引用,‌无需手动释放‌,其生命周期与输入的 info 对象绑定。

典型用法示例

  1. 解析 XML 并查找接口

    GDBusNodeInfo *info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
    if (info != NULL) {GDBusInterfaceInfo *iface_info = g_dbus_node_info_lookup_interface(info, "org.example.Test");if (iface_info != NULL) {g_print("找到接口: %s\n", iface_info->name);}g_dbus_node_info_unref(info); // 释放节点信息
    }
    
  2. 验证接口方法是否存在
    结合 g_dbus_interface_info_lookup_method 可进一步检查接口中的方法:

    GDBusMethodInfo *method_info = g_dbus_interface_info_lookup_method(iface_info, "ExampleMethod"
    );
    

应用场景

  1. 动态接口注册
    在 D-Bus 服务启动时,通过此函数快速定位需注册的接口,避免硬编码。
  2. 客户端代理验证
    客户端在调用远程方法前,可先验证接口是否存在,提高健壮性。
  3. 自动化代码生成
    工具链解析 XML 后,利用此函数遍历接口生成代码桩。

注意事项

  • 线程安全‌:需在主线程调用,非多线程安全。
  • 性能‌:查找时间为 O(n),若频繁调用建议缓存结果。
  • 错误处理‌:始终检查返回值,避免直接解引用 NULL

函数g_dbus_connection_register_object的用法

g_dbus_connection_register_object 是 GLib 中用于将本地对象注册到 D-Bus 总线上的核心函数,其作用是将程序内部对象暴露为 D-Bus 服务,供其他进程调用。以下是详细用法说明:


函数原型

guint g_dbus_connection_register_object (GDBusConnection *connection,const gchar *object_path,GDBusInterfaceInfo *interface_info,const GDBusInterfaceVTable *vtable,gpointer user_data,GDestroyNotify user_data_free_func,GError **error
);

参数说明

  1. connection

    • 类型:GDBusConnection*
    • 作用:已建立的 D-Bus 连接(通过 g_bus_get_sync() 或类似函数获取)。
    • 要求:必须为有效连接,否则注册失败。
  2. object_path

    • 类型:const gchar*
    • 作用:对象路径(如 "/org/example/MyObject"),需符合 D-Bus 路径规范。
    • 注意:路径需唯一,避免与其他服务冲突。
  3. interface_info

    • 类型:GDBusInterfaceInfo*
    • 作用:接口描述信息,通常通过 g_dbus_node_info_new_for_xml() 解析 XML 生成。
    • 示例:包含方法、信号和属性的结构化定义。
  4. vtable

    • 类型:GDBusInterfaceVTable*
    • 作用:定义接口方法的回调函数表(若为 NULL,则仅注册接口但不处理调用)。
    • 关键回调:
      • method_call:处理方法调用请求。
      • get_property / set_property:处理属性访问。
  5. user_data

    • 类型:gpointer
    • 作用:传递给回调函数的用户自定义数据(如对象实例指针)。
  6. user_data_free_func

    • 类型:GDestroyNotify
    • 作用:释放 user_data 的回调函数(可设为 NULL 若无需释放)。
  7. error

    • 类型:GError**
    • 作用:捕获注册过程中的错误(如路径冲突或权限不足)。

返回值

  • 成功时返回注册 ID(guint),用于后续通过 g_dbus_connection_unregister_object() 注销对象。
  • 失败时返回 0 并设置 error 参数。

典型用法示例

  1. 定义接口 XML

    <node><interface name="org.example.Test"><method name="Echo"><arg type="s" name="input" direction="in"/><arg type="s" name="output" direction="out"/></method></interface>
    </node>
    

  2. 注册对象到总线

    GDBusNodeInfo *info = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
    GDBusInterfaceVTable vtable = {.method_call = handle_method_call,
    };
    guint id = g_dbus_connection_register_object(connection,"/org/example/Test",info->interfaces[0],&vtable,NULL,  // user_dataNULL,  // user_data_free_func&error
    );
    if (id == 0) {g_error("注册失败: %s", error->message);
    }
    

  3. 实现方法回调

    static void handle_method_call(GDBusConnection *connection,const gchar *sender,const gchar *object_path,const gchar *interface_name,const gchar *method_name,GVariant *parameters,GDBusMethodInvocation *invocation,gpointer user_data
    ) {if (g_strcmp0(method_name, "Echo") == 0) {const gchar *input;g_variant_get(parameters, "(&s)", &input);g_dbus_method_invocation_return_value(invocation,g_variant_new("(s)", input));}
    }
    

    使用场景

  4. 手动注册对象
    适用于需要直接控制 D-Bus 消息处理的场景,灵活性高但需自行处理底层细节。
  5. 与骨架对象对比
    相比自动生成的骨架(Skeleton)方式,此函数更适合需要自定义消息分发的场景。

示例代码

#include <gio/gio.h>static void method_call_callback (GDBusConnection *connection,const gchar *sender,const gchar *object_path,const gchar *interface_name,const gchar *method_name,GVariant *parameters,GDBusMethodInvocation *invocation,gpointer user_data) {if (g_strcmp0(method_name, "Hello") == 0) {g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", "World"));}
}int main() {GError *error = NULL;GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);GDBusInterfaceInfo *iface_info = ...; // 从XML加载接口信息GDBusInterfaceVTable vtable = { method_call_callback, NULL, NULL };guint reg_id = g_dbus_connection_register_object(conn,"/com/example/MyObject",iface_info,&vtable,NULL,NULL,&error);if (reg_id == 0) {g_printerr("Registration failed: %s\n", error->message);g_error_free(error);return 1;}// 运行主循环保持服务活跃GMainLoop *loop = g_main_loop_new(NULL, FALSE);g_main_loop_run(loop);return 0;
}

注意事项

  1. 线程安全
    回调函数会在注册时的线程默认主循环中执行,需确保线程上下文安全。

  2. 生命周期管理
    注册的对象会持续有效,直到显式注销或连接关闭1。

  3. 错误处理
    若远程调用参数不符合接口定义,自动返回 org.freedesktop.DBus.Error.InvalidArgs 错误。

  4. 性能优化
    频繁调用的服务建议使用骨架(Skeleton)模式,减少动态解析开销。

  5. 替代方案
    对于复杂接口,推荐使用 gdbus-codegen 生成骨架代码,简化开发。

http://www.dtcms.com/a/324674.html

相关文章:

  • 安全运维的核心
  • 使用 iFLOW-CLI GitHub Action 和 Qwen3-Coder 给 GitHub 仓库生成幻灯片风格的文档站点
  • 一个基于 Next.js 和 Puppeteer 的 Markdown 转图片服务,支持 Docker 部署和 API 集成
  • AI绘画:生成唐初秦叔宝全身像提示词
  • reuse: for booting my spring project with mvn in Windows command line
  • 理清C语言中内存操作的函数
  • LeetCode_字符串
  • 《C语言》结构体和联合体练习题--1
  • ROS2 学习笔记
  • 基于百度地图API的社区地图展示技术实现
  • 初识STL
  • ADB简介
  • 【redis初阶】--------Set 集合类型
  • Baumer高防护相机如何通过YoloV8深度学习模型实现道路坑洼的检测识别(C#代码UI界面版)
  • Linux操作系统从入门到实战(十六)冯诺依曼体系结构,操作系统与系统调用和库函数概念
  • API 接入终极指南:实时掌握京东商品动态
  • openpnp - 顶部相机如果超过6.5米影响通讯质量,可以加USB3.0信号放大器延长线
  • SpringAI报错:com.github.victools.jsonschema.generator.AnnotationHelper
  • 北京-4年功能测试2年空窗-报培训班学测开-第七十二天
  • Langchain入门:构建一个本地RAG应用
  • 《Go小技巧易错点100例》第三十七篇
  • 深度解析Linux设备树(DTS):设计原理、实现框架与实例分析
  • 阿里云ECS云服务器临时升级带宽方法
  • JP3-4-MyClub后台前端(三)
  • 胖虎的菜品
  • 一劳永逸解决Mayplotlib绘图中中文字体显示乱码的问题
  • 嵌入式软件分层架构的设计原理与实践验证(有限状态机理解及结构体封装理解)
  • 进度、质量、安全的关系随笔
  • 力扣面试150(52/150)
  • NY155NY170美光固态闪存NY175NY184