summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <jdahlin@async.com.br>2008-04-25 23:50:02 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-04-25 23:50:02 +0000
commit497c5eebcbf4af86ccca15aa87b4be28e76d638c (patch)
tree07c5de63d35f686f314d265b3e31ce08eeca9ce5
parent6296ff6bc14c00a016ce809e595f4c0a96750828 (diff)
downloadgobject-introspection-497c5eebcbf4af86ccca15aa87b4be28e76d638c.tar.gz
Add support for virtual methods. Pair struct FooClass with struct Foo.
2008-04-25 Johan Dahlin <jdahlin@async.com.br> * 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
-rw-r--r--ChangeLog19
-rw-r--r--TODO2
-rw-r--r--giscanner/gidlwriter.py11
-rw-r--r--giscanner/giscannermodule.c90
-rw-r--r--giscanner/gobjecttreebuilder.py26
-rw-r--r--giscanner/sourcescanner.py42
-rw-r--r--giscanner/treebuilder.py48
-rw-r--r--tests/parser/Foo-expected.gidl7
-rw-r--r--tests/parser/foo-object.h2
9 files changed, 195 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index ac869cc7..3c1b4525 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2008-04-25 Johan Dahlin <jdahlin@async.com.br>
+ * 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 <jdahlin@async.com.br>
+
* giscanner/cgobject.py:
* giscanner/gidlwriter.py:
* giscanner/gobjecttreebuilder.py:
diff --git a/TODO b/TODO
index dac81677..0a38bbbc 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 0e1f7893..253327af 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 9ba2296b..933936c3 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 3b9bc069..60df7e0f 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 c0b2044c..26f8dcf8 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 9508bc74..3b8375b7 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 78554823..42592114 100644
--- a/tests/parser/Foo-expected.gidl
+++ b/tests/parser/Foo-expected.gidl
@@ -125,6 +125,13 @@
<parameter name="p1" type="gpointer"/>
</parameters>
</signal>
+ <vfunc name="virtual_method">
+ <return-type type="gboolean"/>
+ <parameters>
+ <parameter name="object" type="FooObject*"/>
+ <parameter name="first_param" type="int"/>
+ </parameters>
+ </vfunc>
</object>
<object name="FooSubobject" parent="FooObject" type-name="FooSubobject" get-type="foo_subobject_get_type">
<constructor name="new" symbol="foo_subobject_new">
diff --git a/tests/parser/foo-object.h b/tests/parser/foo-object.h
index b01034d2..8605f267 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);