gobject-introspection r179 - in trunk: . giscanner tools
- From: johan svn gnome org
- To: svn-commits-list gnome org
- Subject: gobject-introspection r179 - in trunk: . giscanner tools
- Date: Sat, 19 Apr 2008 14:31:03 +0100 (BST)
Author: johan
Date: Sat Apr 19 13:31:03 2008
New Revision: 179
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=179&view=rev
Log:
2008-04-19 Johan Dahlin <johan gnome org>
* giscanner/cgobject.py:
* giscanner/gidlwriter.py:
* giscanner/gobjecttreebuilder.py:
* tools/g-ir-scanner:
Start introspecting get-type functions.
Implement support for GLib/GFlags GTypes.
Add a ctype based GObject binding.
Added:
trunk/giscanner/cgobject.py
trunk/giscanner/gobjecttreebuilder.py
Modified:
trunk/ChangeLog
trunk/giscanner/gidlwriter.py
trunk/tools/g-ir-scanner
Added: trunk/giscanner/cgobject.py
==============================================================================
--- (empty file)
+++ trunk/giscanner/cgobject.py Sat Apr 19 13:31:03 2008
@@ -0,0 +1,149 @@
+# Poor mans GObject python bindings
+# Incidentally portable beyond CPython, due to usage of ctypes
+# Why not PyGObject?
+# - 1) Avoid PyGObject dependency
+# - 2) Low-level binding
+# - 3) Implementation independent
+# - 4) Usage lower in the stack
+#
+# based on defsgen.py (C) 2006 John Finlay
+#
+
+import ctypes
+
+# Constants
+
+TYPE_INVALID = 0
+TYPE_INTERFACE = 8
+TYPE_ENUM = 48
+TYPE_FLAGS = 52
+TYPE_STRING = 64
+TYPE_BOXED = 72
+TYPE_OBJECT = 80
+
+
+# Typedefs
+
+GType = ctypes.c_ulong
+
+
+# Structs
+
+class GTypeClass(ctypes.Structure):
+ _fields_ = [('g_type', GType)]
+
+
+class GTypeInstance(ctypes.Structure):
+ _fields_ = [('g_class', ctypes.POINTER(GTypeClass))]
+
+
+class GEnumValue(ctypes.Structure):
+ _fields_ = [('value', ctypes.c_int),
+ ('value_name', ctypes.c_char_p),
+ ('value_nick', ctypes.c_char_p)]
+
+
+class GFlagsValue(ctypes.Structure):
+ _fields_ = [('value', ctypes.c_uint),
+ ('value_name', ctypes.c_char_p),
+ ('value_nick', ctypes.c_char_p)]
+
+
+class GEnumClass(ctypes.Structure):
+ _fields_ = [('g_type_class', GTypeClass),
+ ('minimum', ctypes.c_int),
+ ('maximum', ctypes.c_int),
+ ('n_values', ctypes.c_uint),
+ ('values', ctypes.POINTER(GEnumValue))]
+
+ def get_values(self):
+ for i in range(self.n_values):
+ yield self.values[i]
+
+
+class GFlagsClass(ctypes.Structure):
+ _fields_ = [('g_type_class', GTypeClass),
+ ('mask', ctypes.c_uint),
+ ('n_values', ctypes.c_uint),
+ ('values', ctypes.POINTER(GFlagsValue))]
+
+ def get_values(self):
+ for i in range(self.n_values):
+ yield self.values[i]
+
+
+class GTypeInterface(ctypes.Structure):
+ _fields_ = [('g_type', GType),
+ ('g_instance_type', GType)]
+
+
+class GParamSpec(ctypes.Structure):
+ _fields_ = [('g_type_instance', GTypeInstance),
+ ('name', ctypes.c_char_p),
+ ('flags', ctypes.c_uint),
+ ('value_type', GType),
+ ('owner_type', GType)]
+
+
+_gobj = ctypes.cdll.LoadLibrary('libgobject-2.0.so')
+_gobj.g_type_init()
+
+
+# Functions
+
+_gobj.g_type_name.restype = ctypes.c_char_p
+def type_name(type_id):
+ return _gobj.g_type_name(type_id)
+
+_gobj.g_type_from_name.argtypes = [ctypes.c_char_p]
+def type_from_name(name):
+ return _gobj.g_type_from_name(name)
+
+def type_fundamental(type_id):
+ return _gobj.g_type_fundamental(type_id)
+
+_gobj.g_type_class_ref.restype = ctypes.POINTER(GTypeClass)
+def type_class_ref(type_id):
+ fundamental_type = type_fundamental(type_id)
+ if fundamental_type == TYPE_INVALID:
+ return None
+ if fundamental_type == TYPE_ENUM:
+ typeclass = GEnumClass
+ elif fundamental_type == TYPE_FLAGS:
+ typeclass = GFlagsClass
+ else:
+ raise NotImplementedError(fundamental_type)
+ ptr = _gobj.g_type_class_ref(type_id)
+ return ctypes.cast(ptr, ctypes.POINTER(typeclass)).contents
+
+_gobj.g_object_class_list_properties.restype = ctypes.POINTER(
+ ctypes.POINTER(GParamSpec))
+def object_class_list_properties(type_id):
+ klass = _gobj.g_type_class_ref(type_id)
+ n = ctypes.c_uint()
+ pspecs = _gobj.g_object_class_list_properties(klass, ctypes.byref(n))
+ for i in range(n.value):
+ yield pspecs[i]
+
+_gobj.g_object_interface_list_properties.restype = ctypes.POINTER(
+ ctypes.POINTER(GParamSpec))
+def object_interface_list_properties(type_id):
+ iface = _gobj.g_type_default_interface_ref(type_id)
+ n = ctypes.c_uint()
+ pspecs = _gobj.g_object_interface_list_properties(iface, ctypes.byref(n))
+ for i in range(n.value):
+ yield pspecs[i]
+
+_gobj.g_type_interfaces.restype = ctypes.POINTER(ctypes.c_int)
+def type_interfaces(type_id):
+ n = ctypes.c_uint()
+ type_ids = _gobj.g_type_interfaces(type_id, ctypes.byref(n))
+ for i in range(n.value):
+ yield type_ids[i]
+
+_gobj.g_type_interface_prerequisites.restype = ctypes.POINTER(ctypes.c_int)
+def type_interface_prerequisites(type_id):
+ n = ctypes.c_uint()
+ type_ids = _gobj.g_type_interface_prerequisites(type_id, ctypes.byref(n))
+ for i in range(n.value):
+ yield type_ids[i]
Modified: trunk/giscanner/gidlwriter.py
==============================================================================
--- trunk/giscanner/gidlwriter.py (original)
+++ trunk/giscanner/gidlwriter.py Sat Apr 19 13:31:03 2008
@@ -1,7 +1,7 @@
+from giscanner.gobjecttreebuilder import GLibEnum, GLibEnumMember, GLibFlags
from giscanner.treebuilder import Enum, Function
from giscanner.xmlwriter import XMLWriter
-
class GIDLWriter(XMLWriter):
def __init__(self, namespace, nodes):
super(GIDLWriter, self).__init__()
@@ -50,11 +50,21 @@
('type', parameter.type)])
def _write_enum(self, enum):
- self.push_tag('enum', [('name', enum.name)])
+ attrs = [('name', enum.name)]
+ tag_name = 'enum'
+ if isinstance(enum, GLibEnum):
+ attrs.append(('get-type', enum.get_type))
+ if isinstance(enum, GLibFlags):
+ tag_name = 'flags'
+
+ self.push_tag(tag_name, attrs)
for member in enum.members:
self._write_member(member)
self.pop_tag()
def _write_member(self, member):
- self.write_tag('member', [('name', member.name),
- ('value', str(member.value))])
+ attrs = [('name', member.name),
+ ('value', str(member.value))]
+ if isinstance(member, GLibEnumMember):
+ attrs.append(('nick', member.nick))
+ self.write_tag('member', attrs)
Added: trunk/giscanner/gobjecttreebuilder.py
==============================================================================
--- (empty file)
+++ trunk/giscanner/gobjecttreebuilder.py Sat Apr 19 13:31:03 2008
@@ -0,0 +1,103 @@
+import ctypes
+
+from giscanner.treebuilder import Enum, Function, Member, Struct
+from giscanner import cgobject
+
+
+class GLibEnum(Enum):
+ def __init__(self, name, members, get_type):
+ Enum.__init__(self, name, members)
+ self.get_type = get_type
+
+
+class GLibFlags(GLibEnum):
+ pass
+
+
+class GLibEnumMember(Member):
+ def __init__(self, name, value, nick):
+ Member.__init__(self, name, value)
+ self.nick = nick
+
+
+class GObjectTreeBuilder(object):
+ def __init__(self):
+ self.inputnodes = []
+ self.outputnodes = []
+ self._library = None
+
+ # Public API
+
+ def get_nodes(self):
+ return self.outputnodes
+
+ def load_library(self, libname):
+ self._library = ctypes.cdll.LoadLibrary(libname)
+
+ def parse(self, nodes):
+ nodes = list(nodes)
+ for node in nodes:
+ self._parse_node(node)
+
+ # Private
+
+ def _call_get_type_function(self, symbol_name):
+ func = getattr(self._library, symbol_name)
+ func.restype = cgobject.GType
+ func.argtypes = []
+ return func()
+
+ def _parse_node(self, node):
+ if isinstance(node, Enum):
+ self._parse_enum(node)
+ elif isinstance(node, Function):
+ self._parse_function(node)
+ elif isinstance(node, Struct):
+ self._parse_struct(node)
+ else:
+ print 'Unhandled node:', node
+
+ def _parse_enum(self, enum):
+ self.outputnodes.append(enum)
+
+ def _parse_function(self, func):
+ if (func.name.endswith('_get_type') and
+ func.retval.type == 'GType' and
+ not func.parameters):
+ symbol = func.name
+ type_id = self._call_get_type_function(symbol)
+ self._parse_gtype(type_id, symbol)
+ return
+ print 'todo', func
+
+ def _parse_struct(self, struct):
+ if (struct.name.startswith('_') or
+ struct.name.endswith('Iface') or
+ struct.name.endswith('Class')):
+ return
+ print 'todo', struct
+
+ def _parse_gtype(self, type_id, symbol):
+ fundamental_type_id = cgobject.type_fundamental(type_id)
+ if (fundamental_type_id == cgobject.TYPE_ENUM or
+ fundamental_type_id == cgobject.TYPE_FLAGS):
+ self._introspect_enum(fundamental_type_id, type_id, symbol)
+ #elif fundamental_type == cgobject.TYPE_OBJECT:
+ # pass
+ else:
+ print 'unhandled GType: %s' % (cgobject.type_name(type_id),)
+
+ def _introspect_enum(self, ftype_id, type_id, symbol):
+ type_class = cgobject.type_class_ref(type_id)
+ if type_class is None:
+ return
+
+ members = []
+ for enum_value in type_class.get_values():
+ members.append(GLibEnumMember(enum_value.value_name,
+ enum_value.value,
+ enum_value.value_nick))
+
+ klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
+ cenum = klass(cgobject.type_name(type_id), members, symbol)
+ self.outputnodes.append(cenum)
Modified: trunk/tools/g-ir-scanner
==============================================================================
--- trunk/tools/g-ir-scanner (original)
+++ trunk/tools/g-ir-scanner Sat Apr 19 13:31:03 2008
@@ -5,6 +5,7 @@
sys.path.insert(0, '.')
from giscanner.gidlwriter import GIDLWriter
+from giscanner.gobjecttreebuilder import GObjectTreeBuilder
from giscanner.sourcescanner import SourceScanner
from giscanner.treebuilder import TreeBuilder
@@ -16,6 +17,9 @@
parser.add_option("-n", "--namespace",
action="store", dest="namespace",
help="namespace of this unit")
+ parser.add_option("-l", "--library",
+ action="store", dest="library",
+ help="library of this unit")
group = optparse.OptionGroup(parser, "Preprocessor options")
group.add_option("-I", help="Pre-processor include file",
@@ -47,7 +51,10 @@
ss.parse_file(filename)
ss.parse_macros()
- builder = TreeBuilder(ss)
+ builder = GObjectTreeBuilder()
+ builder.load_library(options.library)
+ builder.parse(TreeBuilder(ss).get_nodes())
+
writer = GIDLWriter(options.namespace, builder.get_nodes())
print writer.get_xml()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]