使用 pythons Gio-Bindings 在 DBus 上注册对象

Posted

技术标签:

【中文标题】使用 pythons Gio-Bindings 在 DBus 上注册对象【英文标题】:Registering an Object on DBus using pythons Gio-Bindings 【发布时间】:2015-03-17 19:03:29 【问题描述】:

我正在对现有 C 项目进行 Python 克隆。 C 项目连接到自定义 DBus 并在其中提供一个对象以获取回调。

我尝试使用 Python 复制这一点,其代码基本上归结为:

def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
    print('vtable_method_call_cb: %s' % method_name)

connection = Gio.DBusConnection.new_for_address_sync(
    "unix:abstract=gstswitch",
    Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
    None,
    None)

node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)

vtable = Gio.DBusInterfaceVTable()
vtable.method_call(vtable_method_call_cb)
vtable.get_property(None)
vtable.set_property(None)

connection.register_object(
    "/info/duzy/gst/switch/SwitchUI",
    node_info.interfaces[0],
    vtable,
    None,
    None)

vtable.method_call 调用创建vtable 时代码失败(但get_property 也失败,当我注释一个调用时)以下日志/回溯:

** (process:18062): WARNING **: Field method_call: Interface type 2 should have is_pointer set
Traceback (most recent call last):
  File "moo.py", line 69, in <module>
    vtable.method_call(vtable_method_call_cb)
RuntimeError: unable to get the value

我无法在 python 中使用register_object() 找到代码,所以我不确定 Gio 的这一部分是否应该可用,或者它是否不完整。

【问题讨论】:

【参考方案1】:

这当然不是您想听到的,但是您在 GDBus Python 绑定中遇到了4 year old bug,这使得无法在总线上注册对象。很久以前就提出了一个补丁,但每次看起来它真的要登陆时,一些 GNOME 开发人员发现了一些他/她不喜欢的地方,提出了一个新补丁......但什么也没发生明年的大部分时间。这个循环已经发生了3次,不知道有没有希望很快被打破……

基本上 GNOME 开发人员自己或多或少 suggested that people use dbus-python until this issue is finally fixed,所以我猜你应该去 here instead。 :-/

顺便说一句:我认为你的源代码是错误的(除了它不会以任何方式工作的事实)。我认为要创建 VTable,您实际上会写成这样:

vtable = Gio.DBusInterfaceVTable()
vtable.method_call  = vtable_method_call_cb
vtable.get_property = None
vtable.set_property = None

但是由于绑定已损坏,您只是在这里用abort() 交易一个例外...... :-(

如果补丁实际上以当前形式进入python-givtable 将被完全转储(是的!)并且connection.register_object 调用将变为:

connection.register_object_with_closures(
    "/info/duzy/gst/switch/SwitchUI",
    node_info.interfaces[0],
    vtable_method_call_cb, # vtable.method_call
    None,                  # vtable.get_property
    None)                  # vtable.set_property

更新

看来这个问题现在终于解决了!您现在可以使用g_dbus_connection_register_object_with_closures 导出对象:

def vtable_method_call_cb(connection, sender, object_path, interface_name, method_name, parameters, invocation, user_data):
    print('vtable_method_call_cb: %s' % method_name)

connection = Gio.DBusConnection.new_for_address_sync(
    "unix:abstract=gstswitch",
    Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT,
    None,
    None)

node_info = Gio.DBusNodeInfo.new_for_xml(introspection_xml)

connection.register_object(
    "/info/duzy/gst/switch/SwitchUI",
    node_info.interfaces[0],
    vtable_method_call_cb,
    None,
    None)

【讨论】:

感谢您指出这一点。我接受了这个作为答案,因为它有助于澄清 Python 中有关 DBus 的当前情况。我没有找到那个 gnome-bug,所以我非常感谢那个参考。与此同时,我们重写了我们的代码,因此 C-Server 是唯一注册对象的部分,Python-Clients 通过信号获取它的回调——信号是一种在 Gio 支持的总线上推送事件的方法。这可能适合也可能不适合其他人的需求。

以上是关于使用 pythons Gio-Bindings 在 DBus 上注册对象的主要内容,如果未能解决你的问题,请参考以下文章

当python使用“Python.h”调用该c++进程时,如何在python中停止一个c++进程

Python真的这么火吗?哪些公司在使用Python开发

python在linux下的使用

python 使用pymongo在python中使用MongoDB的示例

如何在vscode中使用python编写和运行代码

在 python 内部使用 csound