Vala VAPI和GObject Introspection之间的关系是什么?



首先,一些上下文:我是一名Python开发人员,使用PyGObject编写了一个中型应用程序,利用GObject Introspection来访问GSettings等内容。我的一些Python对象实际上是GObject.GObject的子类,所以我非常广泛地使用GObject。

最近,我注意到某个库将一个 C 库包装在 GObject 中(gexiv2,由 Shotwell/Vala 使用),但它目前不支持内省。我有兴趣为 gexiv2 添加内省支持,以便我可以从 Python 访问它,但我什至不知道从哪里开始这个主题。

当我研究内省和 VAPI 时,我看到很多文档引用了这样一个事实,即 VAPI 可以从内省注释自动生成......但是,对于已经有VAPI但没有内省的项目呢?是否可以在给定 VAPI 的情况下自动生成内省注释?

谢谢。

VAPI 绑定不一定与 GObject 内省有关。例如,有用于POSIX,Linux,libudev和其他绝对不是基于GObject的东西的VAPI绑定。没有直接的方法可以将 VAPI 转换为 GObject 绑定。

但是,如果您有 C 头文件和工作库,那么您通常可以从库中构建 GObject 内省文件。对于 gexiv2,下载并构建源代码,然后执行:

g-ir-scanner -I gexiv2 gexiv2/gexiv2-{metadata,managed-stream,preview-properties,preview-image,log,startup}.h -n GExiv2 --library libgexiv2.la --pkg gobject-2.0

这将产生一个可以在 Python 中使用的 GIR 绑定 (XML)。

好吧,在厌倦了将VAPI定义手动复制到内省注释中的繁琐之后,我编写了这个(粗糙的)脚本来为我做这件事:

#!/bin/env python
import sys
from collections import defaultdict
ANNOTATION = """/**
 * %s:
%s *
 * Returns:%s
 */
"""
PARAMETER = """ * @%s:%s
"""
methods = defaultdict(set)
attrs = defaultdict(dict)
with open(sys.argv[1]) as vapi:
    for line in vapi:
        tokens = line.split()
        try:
            names = tuple(tokens[0].split('.'))
        except IndexError:
            continue
        attrs[names] = {}
        for attribute in tokens[1:]:
            key, val = attribute.split('=')
            if val == '"1"': val = True
            if val == '"0"': val = False
            attrs[names][key] = val
        methods[names[0]]
        if len(names) > 1:
            methods[names[0]].add(names[-1])
for method in methods:
    params = ''
    for param in methods[method]:
        param_attributes = ''
        param_attrs = attrs[(method, param)]
        if param_attrs.get('hidden'):
            param_attributes += ' (skip)'
        if param_attrs.get('is_out'):
            param_attributes += ' (out)'
        if param_attrs.get('transfer_ownership'):
            param_attributes += ' (transfer full)'
        elif 'transfer_ownership' in param_attrs:
            param_attributes += ' (transfer none)'
        if param_attrs.get('array_null_terminated'):
            param_attributes += ' (array zero-terminated=1)'
        if param_attrs.get('array_length_pos'):
            param_attributes += ' (array length=FIXME)'
        if param_attributes:
            param_attributes += ':'
        params += PARAMETER % (param, param_attributes)
    attributes = ''
    method_attrs = attrs[(method,)]
    if method_attrs.get('transfer_ownership'):
        attributes += ' (transfer full)'
    elif 'transfer_ownership' in method_attrs:
        attributes += ' (transfer none)'
    if method_attrs.get('nullable'):
        attributes += ' (allow-none)'
    if method_attrs.get('array_null_terminated'):
        attributes += ' (array zero-terminated=1)'
    if attributes:
        attributes += ':'
    print ANNOTATION % (method, params, attributes)

这显然有一些缺点:它不会将注释插入代码中,它只是打印它们,所以你必须做相当多的复制和粘贴才能将所有内容放入正确的位置。它也不能很好地处理数组,但它至少可以让您知道何时需要手动修复数组。总而言之,运行此脚本然后调整结果的工作量要比手动解析少得多。我把它贴在这里,希望它能被谷歌接受,其他人有一天可能会受益(尽管我非常希望从现在开始所有基于 GObject 的项目都只是从注释开始,然后使用 vapigen)。

最新更新