我正在为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
属性提供此
我如何使用这个GLib.Array我正在通过?
我正在运行Python 2.7.4
答案 0 :(得分:0)
GArray
未正确注释/导出,因此它不会像您期望的那样映射到Python对象。实际上,您可以使用C片段检查最终导出的内容以及Python模块将看到的内容。
info_type = 3 [3 == struct]
n_fields = 2, n_methods = 0
如您所见,只导出了两个字段(len
和data
)。所以,回答你的问题:截至目前,你无法在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
定义为仅包含data
和len
成员的结构,但您可以在garray.c中看到此接口类型是由struct _GRealArray
支持,其中还包含6个成员。
有关 GObject Introspection框架和 Python gi模块的更多信息,请参见:
最后,PyGObject 可以为您无法控制的库启用解决方法,就是将data
成员公开为Python bytes
对象,其长度为等于GArray.len * GRealArray.elt_size
。