From 497c5eebcbf4af86ccca15aa87b4be28e76d638c Mon Sep 17 00:00:00 2001 From: Johan Dahlin Date: Fri, 25 Apr 2008 23:50:02 +0000 Subject: [PATCH] Add support for virtual methods. Pair struct FooClass with struct Foo. 2008-04-25 Johan Dahlin * TODO: * giscanner/gidlwriter.py: * giscanner/giscannermodule.c (pygi_source_directive_new), (directive_get_options), (pygi_source_symbol_new), (symbol_get_base_type), (pygi_source_type_new), (type_get_base_type), (type_get_child_list), (pygi_source_scanner_get_symbols), (pygi_source_scanner_get_directives): * giscanner/gobjecttreebuilder.py: * giscanner/sourcescanner.py: * giscanner/treebuilder.py: * tests/parser/foo-object.h: Add support for virtual methods. Pair struct FooClass with struct Foo. Clean up the SourceScanner bindings a bit. Add a testcase for virtual methods. svn path=/trunk/; revision=226 --- ChangeLog | 19 +++++++++ TODO | 2 - giscanner/gidlwriter.py | 11 +++++ giscanner/giscannermodule.c | 90 ++++++++++++++++++++++++++++------------- giscanner/gobjecttreebuilder.py | 26 +++++++++--- giscanner/sourcescanner.py | 42 ++++++++++++++++--- giscanner/treebuilder.py | 48 +++++++++++++++++----- tests/parser/Foo-expected.gidl | 7 ++++ tests/parser/foo-object.h | 2 + 9 files changed, 195 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac869cc..3c1b452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2008-04-25 Johan Dahlin + * TODO: + * giscanner/gidlwriter.py: + * giscanner/giscannermodule.c (pygi_source_directive_new), + (directive_get_options), (pygi_source_symbol_new), + (symbol_get_base_type), (pygi_source_type_new), + (type_get_base_type), (type_get_child_list), + (pygi_source_scanner_get_symbols), + (pygi_source_scanner_get_directives): + * giscanner/gobjecttreebuilder.py: + * giscanner/sourcescanner.py: + * giscanner/treebuilder.py: + * tests/parser/foo-object.h: + Add support for virtual methods. + Pair struct FooClass with struct Foo. + Clean up the SourceScanner bindings a bit. + Add a testcase for virtual methods. + +2008-04-25 Johan Dahlin + * giscanner/cgobject.py: * giscanner/gidlwriter.py: * giscanner/gobjecttreebuilder.py: diff --git a/TODO b/TODO index dac8167..0a38bbb 100644 --- a/TODO +++ b/TODO @@ -32,8 +32,6 @@ Repository Scanner ------ -- Virtual functions -- Signals - Property.readable/writable, GLibProperty.blurb/nick - Constants - Annotations in external files diff --git a/giscanner/gidlwriter.py b/giscanner/gidlwriter.py index 0e1f789..253327a 100644 --- a/giscanner/gidlwriter.py +++ b/giscanner/gidlwriter.py @@ -110,6 +110,8 @@ class GIDLWriter(XMLWriter): self._write_method(method) for prop in node.properties: self._write_property(prop) + for field in node.fields: + self._write_field(field) for signal in node.signals: self._write_signal(signal) @@ -140,3 +142,12 @@ class GIDLWriter(XMLWriter): with self.tagcontext('callback', attrs): self._write_return_type(func.retval) self._write_parameters(func.parameters) + + def _write_field(self, field): + if isinstance(field, Callback): + self._write_callback(field) + return + + attrs = [('name', field.name), + ('type', str(field.type))] + self.write_tag('field', attrs) diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c index 9ba2296..933936c 100644 --- a/giscanner/giscannermodule.c +++ b/giscanner/giscannermodule.c @@ -62,6 +62,8 @@ typedef struct { GISourceType *type; } PyGISourceType; +static PyObject * pygi_source_type_new (GISourceType *type); + typedef struct { PyObject_HEAD GISourceSymbol *symbol; @@ -82,6 +84,23 @@ NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner); /* Directive */ static PyObject * +pygi_source_directive_new (GISourceDirective *directive) +{ + PyGISourceDirective *self; + + if (directive == NULL) + { + Py_INCREF (Py_None); + return Py_None; + } + + self = (PyGISourceDirective *)PyObject_New (PyGISourceDirective, + &PyGISourceDirective_Type); + self->directive = directive; + return (PyObject*)self; +} + +static PyObject * directive_get_name (PyGISourceDirective *self, void *context) { @@ -110,8 +129,8 @@ directive_get_options (PyGISourceDirective *self, for (l = self->directive->options; l; l = l->next) { - PyObject *item = PyString_FromString(l->data); - PyList_SetItem (list, i++, (PyObject*)item); + PyObject *item = PyString_FromString (l->data); + PyList_SetItem (list, i++, item); Py_INCREF (item); } @@ -129,6 +148,23 @@ static const PyGetSetDef _PyGISourceDirective_getsets[] = { /* Symbol */ static PyObject * +pygi_source_symbol_new (GISourceSymbol *symbol) +{ + PyGISourceSymbol *self; + + if (symbol == NULL) + { + Py_INCREF (Py_None); + return Py_None; + } + + self = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol, + &PyGISourceSymbol_Type); + self->symbol = symbol; + return (PyObject*)self; +} + +static PyObject * symbol_get_type (PyGISourceSymbol *self, void *context) { @@ -146,11 +182,7 @@ static PyObject * symbol_get_base_type (PyGISourceSymbol *self, void *context) { - PyGISourceType *item; - item = (PyGISourceType *)PyObject_New (PyGISourceType, - &PyGISourceType_Type); - item->type = self->symbol->base_type; - return (PyObject*)item; + return pygi_source_type_new (self->symbol->base_type); } static PyObject * @@ -211,6 +243,23 @@ static const PyGetSetDef _PyGISourceSymbol_getsets[] = { /* Type */ static PyObject * +pygi_source_type_new (GISourceType *type) +{ + PyGISourceType *self; + + if (type == NULL) + { + Py_INCREF (Py_None); + return Py_None; + } + + self = (PyGISourceType *)PyObject_New (PyGISourceType, + &PyGISourceType_Type); + self->type = type; + return (PyObject*)self; +} + +static PyObject * type_get_type (PyGISourceType *self, void *context) { @@ -255,11 +304,7 @@ static PyObject * type_get_base_type (PyGISourceType *self, void *context) { - PyGISourceType *item; - item = (PyGISourceType *)PyObject_New (PyGISourceType, - &PyGISourceType_Type); - item->type = self->type->base_type; - return (PyObject*)item; + return pygi_source_type_new (self->type->base_type); } static PyObject * @@ -277,11 +322,8 @@ type_get_child_list (PyGISourceType *self, for (l = self->type->child_list; l; l = l->next) { - PyGISourceSymbol *item; - item = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol, - &PyGISourceSymbol_Type); - item->symbol = l->data; - PyList_SetItem (list, i++, (PyObject*)item); + PyObject *item = pygi_source_symbol_new (l->data); + PyList_SetItem (list, i++, item); Py_INCREF (item); } @@ -398,11 +440,8 @@ pygi_source_scanner_get_symbols (PyGISourceScanner *self) for (l = symbols; l; l = l->next) { - PyGISourceSymbol *item; - item = (PyGISourceSymbol *)PyObject_New (PyGISourceSymbol, - &PyGISourceSymbol_Type); - item->symbol = l->data; - PyList_SetItem (list, i++, (PyObject*)item); + PyObject *item = pygi_source_symbol_new (l->data); + PyList_SetItem (list, i++, item); Py_INCREF (item); } @@ -427,11 +466,8 @@ pygi_source_scanner_get_directives (PyGISourceScanner *self, for (l = directives; l; l = l->next) { - PyGISourceDirective *item; - item = (PyGISourceDirective *)PyObject_New (PyGISourceDirective, - &PyGISourceDirective_Type); - item->directive = l->data; - PyList_SetItem (list, i++, (PyObject*)item); + PyObject *item = pygi_source_directive_new (l->data); + PyList_SetItem (list, i++, item); Py_INCREF (item); } diff --git a/giscanner/gobjecttreebuilder.py b/giscanner/gobjecttreebuilder.py index 3b9bc06..60df7e0 100644 --- a/giscanner/gobjecttreebuilder.py +++ b/giscanner/gobjecttreebuilder.py @@ -111,6 +111,11 @@ class GObjectTreeBuilder(object): for node in nodes: self._parse_node(node) + # Second round, associate GtkButtonClass with GtkButton + for node in self._output_ns.values(): + if isinstance(node, Struct): + self._pair_class_struct(node) + def register_include(self, filename): from .gidlparser import GIDLParser parser = GIDLParser(filename) @@ -267,15 +272,26 @@ class GObjectTreeBuilder(object): return True def _parse_struct(self, struct): - if (struct.name.startswith('_') or - struct.name.endswith('Iface') or - struct.name.endswith('Class')): - return self._add_attribute(struct) def _parse_callback(self, callback): self._add_attribute(callback) + def _pair_class_struct(self, class_node): + name = class_node.name + if (name.endswith('Class') or + name.endswith('Iface')): + name = name[:-5] + elif name.endswith('Interface'): + name = name[:-9] + else: + return + + node = self._output_ns.get(self._resolve_type_name(name)) + del self._output_ns[class_node.name] + for field in class_node.fields[1:]: + node.fields.append(field) + def _introspect_type(self, type_id, symbol): fundamental_type_id = cgobject.type_fundamental(type_id) if (fundamental_type_id == cgobject.TYPE_ENUM or @@ -327,7 +343,6 @@ class GObjectTreeBuilder(object): self._introspect_properties(node, type_id) self._introspect_signals(node, type_id) self._add_attribute(node) - self._remove_attribute(type_name) self._register_internal_type(type_name, node) def _introspect_boxed(self, type_id, symbol): @@ -335,7 +350,6 @@ class GObjectTreeBuilder(object): node = GLibBoxed(self._strip_namespace_object(type_name), type_name, symbol) self._add_attribute(node) - self._remove_attribute(type_name) self._register_internal_type(type_name, node) def _introspect_properties(self, node, type_id): diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py index c0b2044..26f8dcf 100644 --- a/giscanner/sourcescanner.py +++ b/giscanner/sourcescanner.py @@ -4,18 +4,48 @@ import subprocess import giscanner +class SourceType(object): + def __init__(self, scanner, stype): + self._scanner = scanner + self._stype = stype + + @property + def type(self): + return self._stype.type + + @property + def base_type(self): + if self._stype.base_type is not None: + return SourceType(self._scanner, self._stype.base_type) + + @property + def name(self): + return self._stype.name + + @property + def child_list(self): + for symbol in self._stype.child_list: + if symbol is None: + continue + yield SourceSymbol(self._scanner, symbol) + + class SourceSymbol(object): - def __init__(self, symbol, directives): + def __init__(self, scanner, symbol): + self._scanner = scanner self._symbol = symbol - self._directives = directives def directives(self): mapping = {} - for directive in self._directives: + for directive in self._scanner.get_directives(self._symbol.ident): mapping[directive.name] = directive.options return mapping @property + def const_int(self): + return self._symbol.const_int + + @property def ident(self): return self._symbol.ident @@ -25,7 +55,8 @@ class SourceSymbol(object): @property def base_type(self): - return self._symbol.base_type + if self._symbol.base_type is not None: + return SourceType(self._scanner, self._symbol.base_type) class SourceScanner(object): @@ -66,8 +97,7 @@ class SourceScanner(object): def get_symbols(self): for symbol in self._scanner.get_symbols(): - yield SourceSymbol( - symbol, self._scanner.get_directives(symbol.ident)) + yield SourceSymbol(self._scanner, symbol) def dump(self): print '-'*30 diff --git a/giscanner/treebuilder.py b/giscanner/treebuilder.py index 9508bc7..3b8375b 100644 --- a/giscanner/treebuilder.py +++ b/giscanner/treebuilder.py @@ -14,8 +14,13 @@ class Function(Node): self.symbol = symbol def __repr__(self): - return 'Function(%r, %r, %r)' % (self.name, self.retval, - self.parameters) + return '%s(%r, %r, %r)' % (self.__class__.__name__, + self.name, self.retval, + self.parameters) + + +class VFunction(Function): + pass class Parameter(Node): @@ -48,6 +53,10 @@ class Member(Node): class Struct(Node): + def __init__(self, name): + Node.__init__(self, name) + self.fields = [] + def __repr__(self): return 'Struct(%r)' % (self.name,) @@ -69,6 +78,7 @@ class Class(Node): self.methods = [] self.constructors = [] self.properties = [] + self.fields = [] def __repr__(self): return '%s(%r, %r, %r)' % ( @@ -81,6 +91,7 @@ class Interface(Node): Node.__init__(self, name) self.methods = [] self.properties = [] + self.fields = [] def __repr__(self): return '%s(%r, %r)' % ( @@ -125,7 +136,8 @@ class TreeBuilder(object): def __init__(self, generator): self.generator = generator self.nodes = [] - + self._output_ns = {} + self._typedefs_ns = {} self._traverse() def get_nodes(self): @@ -135,13 +147,14 @@ class TreeBuilder(object): def _traverse(self): for symbol in self.generator.get_symbols(): node = self._traverse_one(symbol) - if node is not None: - self.nodes.append(node) + if node is None: + continue + if node.name.startswith('_'): + continue + self.nodes.append(node) + self._output_ns[node.name] = node def _traverse_one(self, symbol, stype=None): - # Skip private symbols - if symbol.ident.startswith('_'): - return if stype is None: stype = symbol.type if stype == giscanner.CSYMBOL_TYPE_FUNCTION: @@ -149,9 +162,12 @@ class TreeBuilder(object): elif stype == giscanner.CSYMBOL_TYPE_TYPEDEF: if (symbol.base_type.type == giscanner.CTYPE_POINTER and symbol.base_type.base_type.type == giscanner.CTYPE_FUNCTION): - return self._create_callback(symbol) + node = self._create_callback(symbol) + elif symbol.base_type.type == giscanner.CTYPE_STRUCT: + node = self._create_typedef_struct(symbol) else: - return self._traverse_one(symbol, symbol.base_type.type) + node = self._traverse_one(symbol, symbol.base_type.type) + return node elif stype == giscanner.CSYMBOL_TYPE_STRUCT: return self._create_struct(symbol) elif stype == giscanner.CSYMBOL_TYPE_ENUM: @@ -175,6 +191,8 @@ class TreeBuilder(object): return Function(symbol.ident, return_, parameters, symbol.ident) def _create_source_type(self, source_type): + if source_type is None: + return 'None' if source_type.type == giscanner.CTYPE_VOID: value = 'void' elif source_type.type == giscanner.CTYPE_BASIC_TYPE: @@ -222,8 +240,16 @@ class TreeBuilder(object): option,) return return_ + def _create_typedef_struct(self, symbol): + self._typedefs_ns[symbol.base_type.name] = symbol.ident + def _create_struct(self, symbol): - return Struct(symbol.ident) + name = self._typedefs_ns.get(symbol.ident, symbol.ident) + struct = Struct(name) + for child in symbol.base_type.child_list: + struct.fields.append(self._traverse_one(child, + child.base_type.type)) + return struct def _create_callback(self, symbol): parameters = self._create_parameters(symbol.base_type.base_type) diff --git a/tests/parser/Foo-expected.gidl b/tests/parser/Foo-expected.gidl index 7855482..4259211 100644 --- a/tests/parser/Foo-expected.gidl +++ b/tests/parser/Foo-expected.gidl @@ -125,6 +125,13 @@ + + + + + + + diff --git a/tests/parser/foo-object.h b/tests/parser/foo-object.h index b01034d..8605f26 100644 --- a/tests/parser/foo-object.h +++ b/tests/parser/foo-object.h @@ -38,6 +38,8 @@ struct _FooObject struct _FooObjectClass { GObjectClass parent_class; + + gboolean (* virtual_method) (FooObject *object, int first_param); }; gint foo_init (void); -- 2.7.4