Add support for Callbacks
authorJohan Dahlin <jdahlin@async.com.br>
Wed, 23 Apr 2008 01:28:27 +0000 (01:28 +0000)
committerJohan Dahlin <johan@src.gnome.org>
Wed, 23 Apr 2008 01:28:27 +0000 (01:28 +0000)
2008-04-22  Johan Dahlin  <jdahlin@async.com.br>

    * giscanner/gidlwriter.py:
    * giscanner/girwriter.py:
    * giscanner/gobjecttreebuilder.py:
    * giscanner/treebuilder.py:
    Add support for Callbacks

svn path=/trunk/; revision=222

ChangeLog
TODO
giscanner/gidlwriter.py
giscanner/girwriter.py
giscanner/gobjecttreebuilder.py
giscanner/treebuilder.py

index 04c2ea9..1eb6710 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-04-22  Johan Dahlin  <jdahlin@async.com.br>
+
+       * giscanner/gidlwriter.py:
+       * giscanner/girwriter.py:
+       * giscanner/gobjecttreebuilder.py:
+       * giscanner/treebuilder.py:
+       Add support for Callbacks
+
 2008-04-22  Havoc Pennington  <hp@pobox.com>
 
        * girepository/ginvoke.c (g_function_info_invoke): If a symbol is
diff --git a/TODO b/TODO
index d14be15..dac8167 100644 (file)
--- a/TODO
+++ b/TODO
@@ -32,7 +32,6 @@ Repository
 
 Scanner
 ------
-- Callbacks
 - Virtual functions
 - Signals
 - Property.readable/writable, GLibProperty.blurb/nick
index 8d637d9..35fc521 100644 (file)
@@ -2,7 +2,7 @@ from __future__ import with_statement
 
 from .gobjecttreebuilder import (GLibBoxed, GLibEnum, GLibEnumMember,
                                  GLibFlags, GLibObject, GLibInterface)
-from .treebuilder import Class, Enum, Function, Interface
+from .treebuilder import Callback, Class, Enum, Function, Interface
 from .xmlwriter import XMLWriter
 
 
@@ -29,6 +29,8 @@ class GIDLWriter(XMLWriter):
             self._write_class(node)
         elif isinstance(node, GLibBoxed):
             self._write_boxed(node)
+        elif isinstance(node, Callback):
+            self._write_callback(node)
         else:
             print 'WRITER: Unhandled node', node
 
@@ -116,3 +118,9 @@ class GIDLWriter(XMLWriter):
         attrs = [('name', prop.name),
                  ('prop', prop.type)]
         self.write_tag('property', attrs)
+
+    def _write_callback(self, func):
+        attrs = [('name', func.name)]
+        with self.tagcontext('callback', attrs):
+            self._write_return_type(func.retval)
+            self._write_parameters(func.parameters)
index 10a7ed3..54fa262 100644 (file)
@@ -2,7 +2,7 @@ from __future__ import with_statement
 
 from .gobjecttreebuilder import (GLibBoxed, GLibEnum, GLibEnumMember,
                                  GLibFlags, GLibObject, GLibInterface)
-from .treebuilder import Class, Enum, Function, Interface
+from .treebuilder import Callback, Class, Enum, Function, Interface
 from .xmlwriter import XMLWriter
 
 
@@ -35,6 +35,8 @@ class GIRWriter(XMLWriter):
             self._write_class(node)
         elif isinstance(node, GLibBoxed):
             self._write_boxed(node)
+        elif isinstance(node, Callback):
+            self._write_callback(node)
         else:
             print 'WRITER: Unhandled node', node
 
@@ -125,3 +127,10 @@ class GIRWriter(XMLWriter):
         attrs = [('name', prop.name),
                  ('prop', prop.type)]
         self.write_tag('property', attrs)
+
+
+    def _write_callback(self, callback):
+        attrs = [('name', callback.name)]
+        with self.tagcontext('callback', attrs):
+            self._write_return_type(callback.retval)
+            self._write_parameters(callback.parameters)
index 320ddcf..7510c87 100644 (file)
@@ -4,8 +4,8 @@ import os
 
 from . import cgobject
 from .odict import odict
-from .treebuilder import (Class, Enum, Function, Interface, Member, Property,
-                          Struct)
+from .treebuilder import (Callback, Class, Enum, Function, Interface,
+                          Member, Property, Struct)
 
 # Copied from h2defs.py
 _upperstr_pat1 = re.compile(r'([^A-Z])([A-Z])')
@@ -166,8 +166,10 @@ class GObjectTreeBuilder(object):
             self._parse_function(node)
         elif isinstance(node, Struct):
             self._parse_struct(node)
+        elif isinstance(node, Callback):
+            self._parse_callback(node)
         else:
-            print 'Unhandled node:', node
+            print 'GOBJECT BUILDER: Unhandled node:', node
 
     def _parse_enum(self, enum):
         enum.name = self._strip_namespace_object(enum.name)
@@ -263,6 +265,9 @@ class GObjectTreeBuilder(object):
             return
         self._add_attribute(struct)
 
+    def _parse_callback(self, callback):
+        self._add_attribute(callback)
+
     def _introspect_type(self, type_id, symbol):
         fundamental_type_id = cgobject.type_fundamental(type_id)
         if (fundamental_type_id == cgobject.TYPE_ENUM or
index 173dbd6..f2ee906 100644 (file)
@@ -108,6 +108,17 @@ class Property(Node):
             self.name, self.type, self.value)
 
 
+class Callback(Node):
+    def __init__(self, name, retval, parameters):
+        self.name = name
+        self.retval = retval
+        self.parameters = parameters
+
+    def __repr__(self):
+        return 'Callback(%r, %r, %r)' % (
+            self.name, self.retval, self.parameters)
+
+
 class TreeBuilder(object):
     def __init__(self, generator):
         self.generator = generator
@@ -134,7 +145,11 @@ class TreeBuilder(object):
         if stype == giscanner.CSYMBOL_TYPE_FUNCTION:
             return self._create_function(symbol)
         elif stype == giscanner.CSYMBOL_TYPE_TYPEDEF:
-            return self._traverse_one(symbol, symbol.base_type.type)
+            if (symbol.base_type.type == giscanner.CTYPE_POINTER and
+                symbol.base_type.base_type.type == giscanner.CTYPE_FUNCTION):
+                return self._create_callback(symbol)
+            else:
+                return self._traverse_one(symbol, symbol.base_type.type)
         elif stype == giscanner.CSYMBOL_TYPE_STRUCT:
             return self._create_struct(symbol)
         elif stype == giscanner.CSYMBOL_TYPE_ENUM:
@@ -151,12 +166,9 @@ class TreeBuilder(object):
         return Enum(symbol.ident, members)
 
     def _create_function(self, symbol):
-        parameters = []
-        for child in symbol.base_type.child_list:
-            parameters.append(self._create_parameter(child))
-
+        parameters = self._create_parameters(symbol.base_type)
         retval = Return(self._create_source_type(symbol.base_type.base_type))
-        return Function(symbol.ident, retval, parameters, symbol.ident)
+        return Function(symbol.ident, retval, list(parameters), symbol.ident)
 
     def _create_source_type(self, source_type):
         if source_type.type == giscanner.CTYPE_VOID:
@@ -172,6 +184,10 @@ class TreeBuilder(object):
             value = '???'
         return value
 
+    def _create_parameters(self, base_type):
+        for child in base_type.child_list:
+            yield self._create_parameter(child)
+
     def _create_parameter(self, symbol):
         return Parameter(symbol.ident,
                          self._create_source_type(symbol.base_type))
@@ -179,3 +195,7 @@ class TreeBuilder(object):
     def _create_struct(self, symbol):
         return Struct(symbol.ident)
 
+    def _create_callback(self, symbol):
+        parameters = self._create_parameters(symbol.base_type.base_type)
+        retval = Return(self._create_source_type(symbol.base_type.base_type.base_type))
+        return Callback(symbol.ident, retval, list(parameters))