我正在为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
实例。幸运的是,有一个工具链可以帮助您直接从源代码生成这些文件。
要使用此方法,请首先根据此处定义的格式用注释块记录源代码:
接下来,运行g-ir-scanner工具,以生成.gir文件。可以在以下位置找到此工具的文档:
最后,可以使用g-ir-compiler工具创建.typelib文件。它记录在这里:
此过程的逐步说明在此处编写:
这是一个以Java脚本为重点的示例:
我可以保证它有效。一旦生成了提供
GArray
必要细节的.typelib文件,gi模块将为其提供熟悉的序列样式接口(interface),因此您可以像使用列表一样使用它。解决方法
不幸的是,您不能做的是使用gi框架来公开用于处理未指定的GArrays 的函数,而这些函数可能是从其他API获得的!如果您尝试将这些
GArray
中的一个传递到函数中,Python会提示它不是序列类型。就我而言,我正在编写一个GStreamer应用程序,其中一个特定的管道元素正在生成
GstMessage
,其中包含几个GArray
成员。虽然我无法编写访问器函数来直接读取这些成员的内容,但是我发现我可以编写使用GstStructure
的函数,然后读取所需的成员,并将其作为完全指定的GArray返回,从而使gi可以适应于适当的Python顺序。引用
有关
GArray
的更多详细信息,请参见:特别要注意的是,尽管garray.h将
GArray
定义为仅包含data
和len
成员的结构,但是您可以在garray.c中看到此接口(interface)类型由struct _GRealArray
支持,该接口(interface)类型另外包含6个成员。有关 GObject Introspection框架和 Python gi模块的更多信息,请参见:
总结思想
最后,PyGObject可以为您无法控制的库启用变通办法的方法是,将
data
成员公开为Python bytes
对象,其长度等于GArray.len * GRealArray.elt_size
。关于python - 如何在Python中使用GLib.Array?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16618456/