5

我正在为 Rhythmbox 编写一个插件,其中发出的信号是传入一个类型的对象GArrayGLib Arrays的文档向我展示了一些我感兴趣但无法访问的方法。

例如,g_array_index可以让我获得GArray 中的第 n 个项目,但我无法调用它。GArray 对象也没有向我展示任何有用的方法。

要了解我的意思,请在 Python 控制台中执行此操作:

from gi.repository.GLib import Array
x = Array()
dir(x)

这是 dir(x) 的输出

['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__gtype__', '__hash__', '__info__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_free_on_dealloc', 'copy', 'data', 'len']

我看不到从数组中读取的任何方法,也没有看到g_array_indexGLib Arrays 文档页面上提到的方法或任何其他方法。我也试过

    for a in x:
        print a

并且

list(x)

但我收到一个错误:

TypeError: 'Array' object is not iterable

尝试 x[0] 给出了这个:

TypeError: 'Array' object does not support indexing

len属性按预期给出了数组的长度。

data物业给出了这个

在此处输入图像描述

我如何处理我被传递的这个 GLib.Array?

我正在运行 Python 2.7.4

4

2 回答 2

2

介绍

在这个答案中,我将尝试总结我对这个问题的了解,并提供一个解决方案来解决出现这个问题的某些情况。不幸的是,在某些情况下,似乎没有现成的解决方案,尽管我认为可以修改 Python GI 模块以启用变通方法(请参阅下面的结束思想)。

背景

核心问题是这GArray只是对 、 和 的一个相当薄malloc()realloc()包装free()。除此之外,它还添加了一些功能,例如引用计数和对零终止的内置支持。但是,它缺少的一个显着特性是对数组元素类型的任何了解! 这意味着 Python GI(GObject Introspection)模块无法适应任意GArray作为 Python 序列类型工作,而无需进一步了解其中GArray包含的内容。

官方方法

gi 模块支持的使用GArrays 的方法是生成一个 .typelib 文件,其中包含它需要的附加信息,以适应每个特定GArray实例。幸运的是,有一个工具链可以帮助您直接从源代码生成这些文件。

要使用此方法,请首先根据此处定义的格式使用注释块记录您的源代码:

接下来,运行 g-ir-scanner 工具,以生成 .gir 文件。这个工具的文档可以在这里找到:

最后,可以使用 g-ir-compiler 工具来创建 .typelib 文件。它记录在这里:

这个过程的演练写在这里:

这是一个以 Javascript 为重点的:

我可以保证它有效。一旦你生成了一个 .typelib 文件来提供你GArray的 .

解决方法

不幸的是,您不能做的是使用 gi 框架来公开用于处理您可能从其他 API 获得的未指定 GArray 的函数!如果您尝试将其中一个GArrays 传递给您的函数,Python 会抱怨它不是序列类型。

在我的例子中,我正在编写一个 GStreamer 应用程序,其中一个特定的管道元素正在生成GstMessage包含几个GArray成员的 s。虽然我无法编写访问器函数来直接读取这些成员的内容,但我发现我可以编写函数来获取GstStructure,然后读取所需的成员并将其作为完全指定的 GArray 返回,gi 可以将其调整为适当的 Python 序列.

参考

有关 的更多详细信息GArray,请参阅:

特别注意,虽然 garray.h 将 a 定义GArray为仅包含 adatalen成员的结构,但您可以在 garray.c 中看到此接口类型由 支持struct _GRealArray,其中包含额外的 6 个成员。

有关GObject Introspection 框架Python gi 模块的更多信息,请参阅:

结束的想法

最后,PyGObject可以为您无法控制的库启用解决方法,就是将data成员公开为 Pythonbytes对象,长度等于GArray.len * GRealArray.elt_size.

于 2019-10-06T21:13:05.230 回答
0

GArray没有正确注释/导出,因此它不会像您期望的那样映射到 Python 对象。事实上,您可以检查最后的 C 代码段究竟导出了什么以及 Python 模块将看到什么。

info_type = 3 [3 == struct]
n_fields = 2, n_methods = 0

如您所见,仅导出了两个字段 (len和)。data所以,回答你的问题:到目前为止,你还不能真正使用GLib.ArrayPython。

这是代码:

#include <girepository.h>

int
main (int argc, char const* argv[])
{
    GIBaseInfo *info;
    GIStructInfo *struct_info;
    GITypelib *typelib;
    GIInfoType info_type;

    typelib = g_irepository_require (NULL, "GLib", NULL, 0, NULL);
    info = g_irepository_find_by_name (NULL, "GLib", "Array");
    info_type = g_base_info_get_type(info);

    g_print ("info_type = %i [3 == struct]\n", info_type);

    struct_info = (GIStructInfo *) info;

    g_print ("n_fields = %i, n_methods = %i\n",
             g_struct_info_get_n_fields (struct_info),
             g_struct_info_get_n_methods (struct_info));

    g_base_info_unref (info);
    g_typelib_free (typelib);
    return 0;
}
于 2014-09-03T10:40:31.230 回答