我如何使用Python中的GLib.Array?

时间:2013-05-17 21:51:24

标签: python python-2.7 glib

我正在为Rhythmbox编写一个插件,其中signal raised正在传递GArray类型的对象。 GLib 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_index或GLib 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属性提供此

enter image description here

我如何使用这个GLib.Array我正在通过?

我正在运行Python 2.7.4

2 个答案:

答案 0 :(得分:0)

GArray未正确注释/导出,因此它不会像您期望的那样映射到Python对象。实际上,您可以使用C片段检查最终导出的内容以及Python模块将看到的内容。

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

如您所见,只导出了两个字段(lendata)。所以,回答你的问题:截至目前,你无法在Python中使用GLib.Array

以下是代码:

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

答案 1 :(得分:0)

简介

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

背景

核心问题是GArray只是malloc()realloc()free()周围的薄包装。除此之外,它还增加了一些功能,例如引用计数和对零终止的内置支持。但是,它缺少的一个显着特征是对数组元素类型的任何了解!这意味着Python GI(GObject自省)模块无法适应任意GArray来工作Python序列类型,而没有有关GArray包含的内容的进一步信息。

官方方法

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

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

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

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

此过程的逐步说明写在这里:

这里是一个使用Java脚本的人:

我可以保证它有效。生成提供您GArray必要详细信息的.typelib文件后,gi模块将为其提供熟悉的序列样式接口,因此您可以像列表一样使用它。

解决方法

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

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

参考

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

尤其要注意,尽管garray.h将GArray定义为仅包含datalen成员的结构,但您可以在garray.c中看到此接口类型是由struct _GRealArray支持,其中还包含6个成员。

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

结束思想

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