2

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

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

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

谢谢。

4

2 回答 2

2

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)。

于 2012-06-25T22:55:39.437 回答
1

好吧,在厌倦了将 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)。

于 2012-06-30T07:37:16.653 回答