我正在为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数组”文档页面上提到的任何其他方法的信息。我也试过了
    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

最佳答案

介绍

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

背景

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

官方方法

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

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

  • https://wiki.gnome.org/Projects/GObjectIntrospection/Annotations

  • 接下来,运行g-ir-scanner工具,以生成.gir文件。可以在以下位置找到此工具的文档:
  • https://gi.readthedocs.io/en/latest/tools/g-ir-scanner.html

  • 最后,可以使用g-ir-compiler工具创建.typelib文件。它记录在这里:
  • https://gi.readthedocs.io/en/latest/tools/g-ir-compiler.html

  • 此过程的逐步说明在此处编写:
  • https://storageapis.wordpress.com/2014/07/25/minimalistic-example-of-the-glibs-gboxedtype-usage/

  • 这是一个以Java脚本为重点的示例:
  • http://helgo.net/simon/introspection-tutorial/index.xhtml

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

    解决方法

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

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

    引用

    有关GArray的更多详细信息,请参见:
  • https://developer.gnome.org/glib/stable/glib-Arrays.html
  • https://github.com/GNOME/glib/blob/master/glib/garray.h
  • https://github.com/GNOME/glib/blob/master/glib/garray.c

  • 特别要注意的是,尽管garray.h将GArray定义为仅包含datalen成员的结构,但是您可以在garray.c中看到此接口(interface)类型由struct _GRealArray支持,该接口(interface)类型另外包含6个成员。

    有关 GObject Introspection框架 Python gi模块的更多信息,请参见:
  • https://gi.readthedocs.io/en/latest/
  • https://developer.gnome.org/gi/unstable/
  • https://pygobject.readthedocs.io/en/latest/

  • 总结思想

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

    关于python - 如何在Python中使用GLib.Array?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16618456/

    10-09 19:53