codegen/: Backport pygtk 2.6.2 codegen

Original commit message from CVS:
* codegen/argtypes.py:
* codegen/codegen.py:
* codegen/definitions.py:
* codegen/defsparser.py:
* codegen/h2def.py:
* codegen/mergedefs.py:
* codegen/reversewrapper.py:
Backport pygtk 2.6.2 codegen
* gst/gst-types.defs:
Added fields for Buffer, Event, Message and Query
Added pre-roll for enum ElementStateReturn
* gst/gst.defs:
Added (define-method for gst_structure_nth_field_name()
* gst/gstelement.override:
Added override for gst_element_get_state
* gst/gstcaps.override:
re-enabled structure functions
This commit is contained in:
Edward Hervey 2005-06-26 13:59:34 +00:00
parent febd74992d
commit 685c434a03
12 changed files with 1489 additions and 162 deletions

View file

@ -1,3 +1,27 @@
2005-06-26 Edward Hervey <edward@fluendo.com>
* codegen/argtypes.py:
* codegen/codegen.py:
* codegen/definitions.py:
* codegen/defsparser.py:
* codegen/h2def.py:
* codegen/mergedefs.py:
* codegen/reversewrapper.py:
Backport pygtk 2.6.2 codegen
* gst/gst-types.defs:
Added fields for Buffer, Event, Message and Query
Added pre-roll for enum ElementStateReturn
* gst/gst.defs:
Added (define-method for gst_structure_nth_field_name()
* gst/gstelement.override:
Added override for gst_element_get_state
* gst/gstcaps.override:
re-enabled structure functions
2005-06-26 Edward Hervey <edward@fluendo.com> 2005-06-26 Edward Hervey <edward@fluendo.com>
* codegen/argtypes.py: * codegen/argtypes.py:

View file

@ -3,6 +3,7 @@ import sys
import string import string
import traceback import traceback
import keyword import keyword
import struct
class VarList: class VarList:
"""Nicely format a C variable list""" """Nicely format a C variable list"""
@ -188,13 +189,82 @@ class IntArg(ArgType):
info.varlist.add('int', 'ret') info.varlist.add('int', 'ret')
info.codeafter.append(' return PyInt_FromLong(ret);') info.codeafter.append(' return PyInt_FromLong(ret);')
class UIntArg(ArgType):
def write_param(self, ptype, pname, pdflt, pnull, info):
if pdflt:
info.varlist.add(ptype, pname + ' = ' + pdflt)
else:
info.varlist.add(ptype, pname)
info.arglist.append(pname)
info.add_parselist('I', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add(ptype, 'ret')
info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
class SizeArg(ArgType):
if struct.calcsize('P') <= struct.calcsize('l'):
llp64 = True
else:
llp64 = False
def write_param(self, ptype, pname, pdflt, pnull, info):
if pdflt:
info.varlist.add(ptype, pname + ' = ' + pdflt)
else:
info.varlist.add(ptype, pname)
info.arglist.append(pname)
if self.llp64:
info.add_parselist('k', ['&' + pname], [pname])
else:
info.add_parselist('K', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add(ptype, 'ret')
if self.llp64:
info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);\n')
else:
info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
class SSizeArg(ArgType):
if struct.calcsize('P') <= struct.calcsize('l'):
llp64 = True
else:
llp64 = False
def write_param(self, ptype, pname, pdflt, pnull, info):
if pdflt:
info.varlist.add(ptype, pname + ' = ' + pdflt)
else:
info.varlist.add(ptype, pname)
info.arglist.append(pname)
if self.llp64:
info.add_parselist('l', ['&' + pname], [pname])
else:
info.add_parselist('L', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add(ptype, 'ret')
if self.llp64:
info.codeafter.append(' return PyLong_FromLongLong(ret);\n')
else:
info.codeafter.append(' return PyLong_FromLong(ret);\n')
class LongArg(ArgType):
def write_param(self, ptype, pname, pdflt, pnull, info):
if pdflt:
info.varlist.add(ptype, pname + ' = ' + pdflt)
else:
info.varlist.add(ptype, pname)
info.arglist.append(pname)
info.add_parselist('l', ['&' + pname], [pname])
def write_return(self, ptype, ownsreturn, info):
info.varlist.add(ptype, 'ret')
info.codeafter.append(' return PyInt_FromLong(ret);\n')
class BoolArg(IntArg): class BoolArg(IntArg):
def write_return(self, ptype, ownsreturn, info): def write_return(self, ptype, ownsreturn, info):
info.varlist.add('int', 'ret') info.varlist.add('int', 'ret')
info.varlist.add('PyObject', '*py_ret') info.codeafter.append(' return PyBool_FromLong(ret);\n')
info.codeafter.append(' py_ret = ret ? Py_True : Py_False;\n'
' Py_INCREF(py_ret);\n'
' return py_ret;')
class TimeTArg(ArgType): class TimeTArg(ArgType):
def write_param(self, ptype, pname, pdflt, pnull, info): def write_param(self, ptype, pname, pdflt, pnull, info):
@ -333,7 +403,7 @@ class EnumArg(ArgType):
info.add_parselist('O', ['&py_' + pname], [pname]); info.add_parselist('O', ['&py_' + pname], [pname]);
def write_return(self, ptype, ownsreturn, info): def write_return(self, ptype, ownsreturn, info):
info.varlist.add('gint', 'ret') info.varlist.add('gint', 'ret')
info.codeafter.append(' return PyInt_FromLong(ret);') info.codeafter.append(' return pyg_enum_from_gtype(%s, ret);' % self.typecode)
class FlagsArg(ArgType): class FlagsArg(ArgType):
flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n' flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gint *)&%(name)s))\n'
@ -356,7 +426,7 @@ class FlagsArg(ArgType):
info.add_parselist('O', ['&py_' + pname], [pname]) info.add_parselist('O', ['&py_' + pname], [pname])
def write_return(self, ptype, ownsreturn, info): def write_return(self, ptype, ownsreturn, info):
info.varlist.add('guint', 'ret') info.varlist.add('guint', 'ret')
info.codeafter.append(' return PyInt_FromLong(ret);') info.codeafter.append(' return pyg_flags_from_gtype(%s, ret);' % self.typecode)
class ObjectArg(ArgType): class ObjectArg(ArgType):
# should change these checks to more typesafe versions that check # should change these checks to more typesafe versions that check
@ -404,7 +474,7 @@ class ObjectArg(ArgType):
info.codebefore.append(self.dflt % {'name':pname, info.codebefore.append(self.dflt % {'name':pname,
'cast':self.cast}) 'cast':self.cast})
info.arglist.append(pname) info.arglist.append(pname)
info.add_parselist('O', ['&Py%s_Type' % self.objname, info.add_parselist('O!', ['&Py%s_Type' % self.objname,
'&py_' + pname], [pname]) '&py_' + pname], [pname])
else: else:
info.varlist.add('PyGObject', '*' + pname) info.varlist.add('PyGObject', '*' + pname)
@ -417,7 +487,8 @@ class ObjectArg(ArgType):
if ownsreturn: if ownsreturn:
info.varlist.add('PyObject', '*py_ret') info.varlist.add('PyObject', '*py_ret')
info.codeafter.append(' py_ret = pygobject_new((GObject *)ret);\n' info.codeafter.append(' py_ret = pygobject_new((GObject *)ret);\n'
' g_object_unref(ret);\n' ' if (ret != NULL)\n'
' g_object_unref(ret);\n'
' return py_ret;') ' return py_ret;')
else: else:
info.codeafter.append(' /* pygobject_new handles NULL checking */\n' + info.codeafter.append(' /* pygobject_new handles NULL checking */\n' +
@ -620,18 +691,28 @@ class PointerArg(ArgType):
' return pyg_pointer_new(' + self.typecode + ', &ret);') ' return pyg_pointer_new(' + self.typecode + ', &ret);')
class AtomArg(IntArg): class AtomArg(IntArg):
dflt = ' if (py_%(name)s) {\n' \
' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \
' if (PyErr_Occurred())\n' \
' return NULL;\n' \
' }\n'
atom = (' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' atom = (' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n'
' if (PyErr_Occurred())\n' ' if (PyErr_Occurred())\n'
' return NULL;\n') ' return NULL;\n')
def write_param(self, ptype, pname, pdflt, pnull, info): def write_param(self, ptype, pname, pdflt, pnull, info):
info.varlist.add('GdkAtom', pname) if pdflt:
info.varlist.add('PyObject', '*py_' + pname + ' = NULL') info.varlist.add('GdkAtom', pname + ' = ' + pdflt)
info.codebefore.append(self.atom % {'name': pname}) info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
info.arglist.append(pname) info.codebefore.append(self.dflt % {'name': pname})
else:
info.varlist.add('GdkAtom', pname)
info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
info.codebefore.append(self.atom % {'name': pname})
info.arglist.append(pname)
info.add_parselist('O', ['&py_' + pname], [pname]) info.add_parselist('O', ['&py_' + pname], [pname])
def write_return(self, ptype, ownsreturn, info): def write_return(self, ptype, ownsreturn, info):
info.varlist.add('GdkAtom', 'ret') info.varlist.add('GdkAtom', 'ret')
info.codeafter.append(' return PyGdkAtom_New(ret);') info.codeafter.append(' return PyString_FromString(gdk_atom_name(ret));')
class GTypeArg(ArgType): class GTypeArg(ArgType):
gtype = (' if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n' gtype = (' if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n'
@ -669,12 +750,6 @@ class GtkTreePathArg(ArgType):
' return NULL;\n' ' return NULL;\n'
' }\n' ' }\n'
' }\n') ' }\n')
null = (' if (PyTuple_Check(py_%(name)s))\n'
' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
' else if (py_%(name)s != Py_None) {\n'
' PyErr_SetString(PyExc_TypeError, "%(name)s should be a GtkTreePath or None");\n'
' return NULL;\n'
' }\n')
freepath = (' if (%(name)s)\n' freepath = (' if (%(name)s)\n'
' gtk_tree_path_free(%(name)s);\n') ' gtk_tree_path_free(%(name)s);\n')
def __init__(self): def __init__(self):
@ -761,9 +836,16 @@ class PyObjectArg(ArgType):
class ArgMatcher: class ArgMatcher:
def __init__(self): def __init__(self):
self.argtypes = {} self.argtypes = {}
self.reverse_argtypes = {}
self.reverse_rettypes = {}
def register(self, ptype, handler): def register(self, ptype, handler):
self.argtypes[ptype] = handler self.argtypes[ptype] = handler
def register_reverse(self, ptype, handler):
self.reverse_argtypes[ptype] = handler
def register_reverse_ret(self, ptype, handler):
self.reverse_rettypes[ptype] = handler
def register_enum(self, ptype, typecode): def register_enum(self, ptype, typecode):
if typecode is None: if typecode is None:
typecode = "G_TYPE_NONE" typecode = "G_TYPE_NONE"
@ -806,6 +888,39 @@ class ArgMatcher:
if ptype[:8] == 'GdkEvent' and ptype[-1] == '*': if ptype[:8] == 'GdkEvent' and ptype[-1] == '*':
return self.argtypes['GdkEvent*'] return self.argtypes['GdkEvent*']
raise raise
def _get_reverse_common(self, ptype, registry):
props = dict(c_type=ptype)
try:
return registry[ptype], props
except KeyError:
try:
handler = self.argtypes[ptype]
except KeyError:
if ptype.startswith('GdkEvent') and ptype.endswith('*'):
handler = self.argtypes['GdkEvent*']
else:
raise
if isinstance(handler, ObjectArg):
return registry['GObject*'], props
elif isinstance(handler, EnumArg):
props['typecode'] = handler.typecode
props['enumname'] = handler.enumname
return registry['GEnum'], props
elif isinstance(handler, FlagsArg):
props['typecode'] = handler.typecode
props['flagname'] = handler.flagname
return registry['GFlags'], props
elif isinstance(handler, BoxedArg):
props['typecode'] = handler.typecode
props['typename'] = handler.typename
return registry['GBoxed'], props
else:
raise
def get_reverse(self, ptype):
return self._get_reverse_common(ptype, self.reverse_argtypes)
def get_reverse_ret(self, ptype):
return self._get_reverse_common(ptype, self.reverse_rettypes)
def object_is_a(self, otype, parent): def object_is_a(self, otype, parent):
if otype == None: return 0 if otype == None: return 0
if otype == parent: return 1 if otype == parent: return 1
@ -844,19 +959,24 @@ matcher.register('gunichar', arg)
arg = IntArg() arg = IntArg()
matcher.register('int', arg) matcher.register('int', arg)
matcher.register('gint', arg) matcher.register('gint', arg)
matcher.register('guint', arg)
matcher.register('short', arg) matcher.register('short', arg)
matcher.register('gshort', arg) matcher.register('gshort', arg)
matcher.register('gushort', arg) matcher.register('gushort', arg)
matcher.register('long', arg) matcher.register('gsize', SizeArg())
matcher.register('glong', arg) matcher.register('gssize', SSizeArg())
matcher.register('gsize', arg)
matcher.register('gssize', arg)
matcher.register('guint8', arg) matcher.register('guint8', arg)
matcher.register('gint8', arg) matcher.register('gint8', arg)
matcher.register('guint16', arg) matcher.register('guint16', arg)
matcher.register('gint16', arg) matcher.register('gint16', arg)
matcher.register('gint32', arg) matcher.register('gint32', arg)
matcher.register('GTime', arg)
arg = LongArg()
matcher.register('long', arg)
matcher.register('glong', arg)
arg = UIntArg()
matcher.register('guint', arg)
arg = BoolArg() arg = BoolArg()
matcher.register('gboolean', arg) matcher.register('gboolean', arg)

View file

@ -1,6 +1,32 @@
import sys, os, string import sys, os, string
import getopt, traceback, keyword import getopt, traceback, keyword
import defsparser, argtypes, override import defsparser, argtypes, override
import definitions
import reversewrapper
class Coverage(object):
def __init__(self, name):
self.name = name
self.wrapped = 0
self.not_wrapped = 0
def declare_wrapped(self):
self.wrapped += 1
def declare_not_wrapped(self):
self.not_wrapped += 1
def printstats(self):
total = (self.wrapped + self.not_wrapped)
if total:
print >> sys.stderr, "***INFO*** The coverage of %s is %.2f%% (%i/%i)" %\
(self.name, float(self.wrapped*100)/total, self.wrapped, total)
else:
print >> sys.stderr, "***INFO*** There are no declared %s." %\
(self.name, )
functions_coverage = Coverage("global functions")
methods_coverage = Coverage("methods")
vproxies_coverage = Coverage("virtual proxies")
vaccessors_coverage = Coverage("virtual accessors")
iproxies_coverage = Coverage("interface proxies")
def exc_info(): def exc_info():
#traceback.print_exc() #traceback.print_exc()
@ -60,7 +86,7 @@ class Wrapper:
' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n' \ ' sizeof(%(tp_basicsize)s), /* tp_basicsize */\n' \
' 0, /* tp_itemsize */\n' \ ' 0, /* tp_itemsize */\n' \
' /* methods */\n' \ ' /* methods */\n' \
' (destructor)0, /* tp_dealloc */\n' \ ' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n' \
' (printfunc)0, /* tp_print */\n' \ ' (printfunc)0, /* tp_print */\n' \
' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' \ ' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' \
' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' \ ' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' \
@ -72,13 +98,13 @@ class Wrapper:
' (hashfunc)%(tp_hash)s, /* tp_hash */\n' \ ' (hashfunc)%(tp_hash)s, /* tp_hash */\n' \
' (ternaryfunc)%(tp_call)s, /* tp_call */\n' \ ' (ternaryfunc)%(tp_call)s, /* tp_call */\n' \
' (reprfunc)%(tp_str)s, /* tp_str */\n' \ ' (reprfunc)%(tp_str)s, /* tp_str */\n' \
' (getattrofunc)0, /* tp_getattro */\n' \ ' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n' \
' (setattrofunc)0, /* tp_setattro */\n' \ ' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n' \
' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' \ ' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' \
' Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */\n' \ ' %(tp_flags)s, /* tp_flags */\n' \
' NULL, /* Documentation string */\n' \ ' NULL, /* Documentation string */\n' \
' (traverseproc)0, /* tp_traverse */\n' \ ' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n' \
' (inquiry)0, /* tp_clear */\n' \ ' (inquiry)%(tp_clear)s, /* tp_clear */\n' \
' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' \ ' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' \
' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' \ ' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' \
' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' \ ' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' \
@ -98,11 +124,13 @@ class Wrapper:
' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n' \ ' (inquiry)%(tp_is_gc)s /* tp_is_gc */\n' \
'};\n\n' '};\n\n'
slots_list = ['tp_getattr', 'tp_setattr', 'tp_compare', 'tp_repr', slots_list = ['tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro',
'tp_compare', 'tp_repr',
'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash', 'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash',
'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter', 'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter',
'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init', 'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init',
'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc'] 'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc',
'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags']
getter_tmpl = \ getter_tmpl = \
'static PyObject *\n' \ 'static PyObject *\n' \
@ -145,6 +173,27 @@ class Wrapper:
'%(codeafter)s\n' \ '%(codeafter)s\n' \
'}\n\n' '}\n\n'
virtual_accessor_tmpl = \
'static PyObject *\n' \
'_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' \
'{\n' \
' gpointer klass;\n' \
'%(varlist)s' \
'%(parseargs)s' \
'%(codebefore)s' \
' klass = g_type_class_ref(pyg_type_from_object(cls));\n' \
' if (%(class_cast_macro)s(klass)->%(virtual)s)\n' \
' %(setreturn)s%(class_cast_macro)s(klass)->%(virtual)s(%(arglist)s);\n' \
' else {\n' \
' PyErr_SetString(PyExc_NotImplementedError, ' \
'"virtual method %(name)s not implemented");\n' \
' g_type_class_unref(klass);\n' \
' return NULL;\n' \
' }\n' \
' g_type_class_unref(klass);\n' \
'%(codeafter)s\n' \
'}\n\n'
# template for method calls # template for method calls
constructor_tmpl = None constructor_tmpl = None
method_tmpl = None method_tmpl = None
@ -173,6 +222,8 @@ class Wrapper:
def write_class(self): def write_class(self):
self.fp.write('\n/* ----------- ' + self.objinfo.c_name + ' ----------- */\n\n') self.fp.write('\n/* ----------- ' + self.objinfo.c_name + ' ----------- */\n\n')
substdict = self.get_initial_class_substdict() substdict = self.get_initial_class_substdict()
if not substdict.has_key('tp_flags'):
substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE'
substdict['typename'] = self.objinfo.c_name substdict['typename'] = self.objinfo.c_name
if self.overrides.modulename: if self.overrides.modulename:
substdict['classname'] = '%s.%s' % (self.overrides.modulename, substdict['classname'] = '%s.%s' % (self.overrides.modulename,
@ -189,8 +240,6 @@ class Wrapper:
# handle slots ... # handle slots ...
for slot in self.slots_list: for slot in self.slots_list:
if substdict.has_key(slot) and substdict[slot] != '0':
continue
slotname = '%s.%s' % (self.objinfo.c_name, slot) slotname = '%s.%s' % (self.objinfo.c_name, slot)
slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot) slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot)
@ -201,10 +250,13 @@ class Wrapper:
self.write_function(slotname, data) self.write_function(slotname, data)
substdict[slot] = slotfunc substdict[slot] = slotfunc
else: else:
substdict[slot] = '0' if not substdict.has_key(slot):
substdict[slot] = '0'
self.fp.write(self.type_tmpl % substdict) self.fp.write(self.type_tmpl % substdict)
self.write_virtuals()
def write_function_wrapper(self, function_obj, template, def write_function_wrapper(self, function_obj, template,
handle_return=0, is_method=0, kwargs_needed=0, handle_return=0, is_method=0, kwargs_needed=0,
substdict=None): substdict=None):
@ -223,11 +275,12 @@ class Wrapper:
if function_obj.varargs: if function_obj.varargs:
raise ValueError, "varargs functions not supported" raise ValueError, "varargs functions not supported"
for ptype, pname, pdflt, pnull in function_obj.params: for param in function_obj.params:
if pdflt and '|' not in info.parsestr: if param.pdflt and '|' not in info.parsestr:
info.add_parselist('|', [], []) info.add_parselist('|', [], [])
handler = argtypes.matcher.get(ptype) handler = argtypes.matcher.get(param.ptype)
handler.write_param(ptype, pname, pdflt, pnull, info) handler.write_param(param.ptype, param.pname, param.pdflt,
param.pnull, info)
substdict['setreturn'] = '' substdict['setreturn'] = ''
if handle_return: if handle_return:
@ -249,7 +302,7 @@ class Wrapper:
if self.objinfo: if self.objinfo:
substdict['typename'] = self.objinfo.c_name substdict['typename'] = self.objinfo.c_name
substdict['cname'] = function_obj.c_name substdict.setdefault('cname', function_obj.c_name)
substdict['varlist'] = info.get_varlist() substdict['varlist'] = info.get_varlist()
substdict['typecodes'] = info.parsestr substdict['typecodes'] = info.parsestr
substdict['parselist'] = info.get_parselist() substdict['parselist'] = info.get_parselist()
@ -284,6 +337,16 @@ class Wrapper:
data = self.overrides.override(funcname) data = self.overrides.override(funcname)
self.write_function(funcname, data) self.write_function(funcname, data)
else: else:
# ok, a hack to determine if we should use new-style constructores :P
if getattr(self, 'write_property_based_constructor', None) is not None:
if (len(constructor.params) == 0 or
isinstance(constructor.params[0], definitions.Property)):
# write_property_based_constructor is only
# implemented in GObjectWrapper
return self.write_property_based_constructor(constructor)
else:
print >> sys.stderr, "Warning: generating old-style constructor for",\
constructor.c_name
# write constructor from template ... # write constructor from template ...
code = self.write_function_wrapper(constructor, code = self.write_function_wrapper(constructor,
self.constructor_tmpl, self.constructor_tmpl,
@ -294,19 +357,22 @@ class Wrapper:
except: except:
sys.stderr.write('Could not write constructor for %s: %s\n' sys.stderr.write('Could not write constructor for %s: %s\n'
% (self.objinfo.c_name, exc_info())) % (self.objinfo.c_name, exc_info()))
# this is a hack ... initfunc = self.write_noconstructor()
if not hasattr(self.overrides, 'no_constructor_written'):
self.fp.write(self.noconstructor)
self.overrides.no_constructor_written = 1
initfunc = 'pygobject_no_constructor'
else: else:
# this is a hack ... initfunc = self.write_default_constructor()
if not hasattr(self.overrides, 'no_constructor_written'):
self.fp.write(self.noconstructor)
self.overrides.no_constructor_written = 1
initfunc = 'pygobject_no_constructor'
return initfunc return initfunc
def write_noconstructor(self):
# this is a hack ...
if not hasattr(self.overrides, 'no_constructor_written'):
self.fp.write(self.noconstructor)
self.overrides.no_constructor_written = 1
initfunc = 'pygobject_no_constructor'
return initfunc
def write_default_constructor(self):
return self.write_noconstructor()
def get_methflags(self, funcname): def get_methflags(self, funcname):
if self.overrides.wants_kwargs(funcname): if self.overrides.wants_kwargs(funcname):
return 'METH_VARARGS|METH_KEYWORDS' return 'METH_VARARGS|METH_KEYWORDS'
@ -321,7 +387,16 @@ class Wrapper:
self.fp.write(data) self.fp.write(data)
self.fp.resetline() self.fp.resetline()
self.fp.write('\n\n') self.fp.write('\n\n')
def _get_class_virtual_substdict(self, meth, cname, parent):
substdict = self.get_initial_method_substdict(meth)
substdict['virtual'] = substdict['name'].split('.')[1]
substdict['cname'] = cname
substdict['class_cast_macro'] = parent.typecode.replace('_TYPE_', '_', 1) + "_CLASS"
substdict['typecode'] = self.objinfo.typecode
substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1)
return substdict
def write_methods(self): def write_methods(self):
methods = [] methods = []
klass = self.objinfo.c_name klass = self.objinfo.c_name
@ -347,7 +422,9 @@ class Wrapper:
{ 'name': fixname(meth.name), { 'name': fixname(meth.name),
'cname': '_wrap_' + method_name, 'cname': '_wrap_' + method_name,
'flags': methflags}) 'flags': methflags})
methods_coverage.declare_wrapped()
except: except:
methods_coverage.declare_not_wrapped()
sys.stderr.write('Could not write method %s.%s: %s\n' sys.stderr.write('Could not write method %s.%s: %s\n'
% (klass, meth.name, exc_info())) % (klass, meth.name, exc_info()))
@ -360,15 +437,21 @@ class Wrapper:
try: try:
data = self.overrides.define(klass, method_name) data = self.overrides.define(klass, method_name)
self.write_function(method_name, data) self.write_function(method_name, data)
self.get_methflags(method_name) methflags = self.get_methflags(method_name)
methods.append(self.methdef_tmpl % methods.append(self.methdef_tmpl %
{ 'name': method_name, { 'name': method_name,
'cname': '_wrap_' + c_name, 'cname': '_wrap_' + c_name,
'flags': methflags}) 'flags': methflags})
methods_coverage.declare_wrapped()
except: except:
methods_coverage.declare_not_wrapped()
sys.stderr.write('Could not write method %s.%s: %s\n' sys.stderr.write('Could not write method %s.%s: %s\n'
% (klass, meth.name, exc_info())) % (klass, meth.name, exc_info()))
# Add GObject virtual method accessors, for chaining to parent
# virtuals from subclasses
methods += self.write_virtual_accessors()
if methods: if methods:
methoddefs = '_Py%s_methods' % self.objinfo.c_name methoddefs = '_Py%s_methods' % self.objinfo.c_name
@ -380,6 +463,112 @@ class Wrapper:
else: else:
methoddefs = 'NULL' methoddefs = 'NULL'
return methoddefs return methoddefs
def write_virtual_accessors(self):
klass = self.objinfo.c_name
methods = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
methflags = self.get_methflags(method_name)
else:
# temporarily add a 'self' parameter as first argument
meth.params.insert(0, definitions.Parameter(
ptype=(self.objinfo.c_name + '*'),
pname='self', pdflt=None, pnull=None))
try:
# write method from template ...
code, methflags = self.write_function_wrapper(meth,
self.virtual_accessor_tmpl, handle_return=True, is_method=False,
substdict=self._get_class_virtual_substdict(meth, method_name, self.objinfo))
self.fp.write(code)
finally:
del meth.params[0]
methods.append(self.methdef_tmpl %
{ 'name': "do_" + fixname(meth.name),
'cname': '_wrap_' + method_name,
'flags': methflags + '|METH_CLASS'})
vaccessors_coverage.declare_wrapped()
except:
vaccessors_coverage.declare_not_wrapped()
sys.stderr.write('Could not write virtual accessor method %s.%s: %s\n'
% (klass, meth.name, exc_info()))
return methods
def write_virtuals(self):
'''Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for GObject virtuals'''
klass = self.objinfo.c_name
virtuals = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
else:
# write virtual proxy ...
ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
wrapper = reversewrapper.ReverseWrapper(
'_wrap_' + method_name, is_static=True)
wrapper.set_return_type(ret(wrapper, **props))
wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
wrapper, "self", method_name="do_" + meth.name,
c_type=(klass + ' *')))
for param in meth.params:
handler, props = argtypes.matcher.get_reverse(param.ptype)
wrapper.add_parameter(handler(wrapper, param.pname, **props))
buf = reversewrapper.MemoryCodeSink()
wrapper.generate(buf)
self.fp.write(buf.flush())
virtuals.append((fixname(meth.name), '_wrap_' + method_name))
vproxies_coverage.declare_wrapped()
except KeyError:
vproxies_coverage.declare_not_wrapped()
virtuals.append((fixname(meth.name), None))
sys.stderr.write('Could not write virtual proxy %s.%s: %s\n'
% (klass, meth.name, exc_info()))
if virtuals:
# Write a 'pygtk class init' function for this object,
# except when the object type is explicitly ignored (like
# GtkPlug and GtkSocket on win32).
if self.overrides.is_ignored(self.objinfo.typecode):
return
class_cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1) + "_CLASS"
cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1)
funcname = "__%s_class_init" % klass
self.objinfo.class_init_func = funcname
have_implemented_virtuals = not not [True for name, cname in virtuals
if cname is not None]
self.fp.write(('\nstatic int\n'
'%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n'
'{\n') % vars())
if have_implemented_virtuals:
self.fp.write(' PyObject *o;\n')
self.fp.write(
' %(klass)sClass *klass = %(class_cast_macro)s(gclass);\n'
% vars())
for name, cname in virtuals:
do_name = 'do_' + name
if cname is None:
self.fp.write('\n /* overriding %(do_name)s '
'is currently not supported */\n' % vars())
else:
self.fp.write('''
if ((o = PyDict_GetItemString(pyclass->tp_dict, "%(do_name)s"))
&& !PyObject_TypeCheck(o, &PyCFunction_Type))
klass->%(name)s = %(cname)s;\n''' % vars())
self.fp.write(' return 0;\n}\n')
def write_getsets(self): def write_getsets(self):
lower_name = self.get_lower_name() lower_name = self.get_lower_name()
@ -456,7 +645,9 @@ class Wrapper:
{ 'name': func.name, { 'name': func.name,
'cname': '_wrap_' + funcname, 'cname': '_wrap_' + funcname,
'flags': methflags }) 'flags': methflags })
functions_coverage.declare_wrapped()
except: except:
functions_coverage.declare_not_wrapped()
sys.stderr.write('Could not write function %s: %s\n' sys.stderr.write('Could not write function %s: %s\n'
% (func.name, exc_info())) % (func.name, exc_info()))
@ -470,7 +661,9 @@ class Wrapper:
{ 'name': funcname, { 'name': funcname,
'cname': '_wrap_' + funcname, 'cname': '_wrap_' + funcname,
'flags': methflags }) 'flags': methflags })
functions_coverage.declare_wrapped()
except: except:
functions_coverage.declare_not_wrapped()
sys.stderr.write('Could not write function %s: %s\n' sys.stderr.write('Could not write function %s: %s\n'
% (funcname, exc_info())) % (funcname, exc_info()))
@ -527,21 +720,101 @@ class GObjectWrapper(Wrapper):
def get_initial_constructor_substdict(self, constructor): def get_initial_constructor_substdict(self, constructor):
substdict = Wrapper.get_initial_constructor_substdict(self, constructor) substdict = Wrapper.get_initial_constructor_substdict(self, constructor)
if argtypes.matcher.object_is_a(self.objinfo.c_name, 'GtkWindow'): if not constructor.caller_owns_return:
substdict['aftercreate'] = " g_object_ref(self->obj); /* we don't own the first reference of windows */\n" substdict['aftercreate'] = " g_object_ref(self->obj);\n"
elif argtypes.matcher.object_is_a(self.objinfo.c_name, 'GtkInvisible'): else:
substdict['aftercreate'] = " g_object_ref(self->obj); /* we don't own the first reference of invisibles */\n" substdict['aftercreate'] = ''
else:
if not constructor.caller_owns_return:
substdict['aftercreate'] = " g_object_ref(self->obj);\n"
else:
substdict['aftercreate'] = ''
return substdict return substdict
def get_initial_method_substdict(self, method): def get_initial_method_substdict(self, method):
substdict = Wrapper.get_initial_method_substdict(self, method) substdict = Wrapper.get_initial_method_substdict(self, method)
substdict['cast'] = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1) substdict['cast'] = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
return substdict return substdict
def write_default_constructor(self):
return '0'
def write_property_based_constructor(self, constructor):
out = self.fp
print >> out, "static int"
print >> out, '_wrap_%s(PyGObject *self, PyObject *args,'\
' PyObject *kwargs)\n{' % constructor.c_name
print >> out, " GType obj_type = pyg_type_from_object((PyObject *) self);"
def py_str_list_to_c(arg):
if arg:
return "{" + ", ".join(map(lambda s: '"' + s + '"', arg)) + ", NULL }"
else:
return "{ NULL }"
classname = '%s.%s' % (self.overrides.modulename, self.objinfo.name)
if constructor.params:
mandatory_arguments = [param for param in constructor.params if not param.optional]
optional_arguments = [param for param in constructor.params if param.optional]
arg_names = py_str_list_to_c([param.argname for param in
mandatory_arguments + optional_arguments])
prop_names = py_str_list_to_c([param.pname for param in
mandatory_arguments + optional_arguments])
print >> out, " GParameter params[%i];" % len(constructor.params)
print >> out, " PyObject *parsed_args[%i] = {NULL, };" % len(constructor.params)
print >> out, " char *arg_names[] = %s;" % arg_names
print >> out, " char *prop_names[] = %s;" % prop_names
print >> out, " guint nparams, i;"
print >> out
if constructor.deprecated is not None:
print >> out, ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\
constructor.deprecated
print >> out, ' return -1;'
print >> out
print >> out, " if (!PyArg_ParseTupleAndKeywords(args, kwargs, ",
template = '"'
if mandatory_arguments:
template += "O"*len(mandatory_arguments)
if optional_arguments:
template += "|" + "O"*len(optional_arguments)
template += ':%s.__init__"' % classname
print >> out, template, ", arg_names",
for i in range(len(constructor.params)):
print >> out, ", &parsed_args[%i]" % i,
print >> out, "))"
print >> out, " return -1;"
print >> out
print >> out, " memset(params, 0, sizeof(GParameter)*%i);" % len(constructor.params)
print >> out, " if (!pyg_parse_constructor_args(obj_type, arg_names, prop_names,"
print >> out, " params, &nparams, parsed_args))"
print >> out, " return -1;"
print >> out, " self->obj = g_object_newv(obj_type, nparams, params);"
print >> out, " for (i = 0; i < nparams; ++i)"
print >> out, " g_value_unset(&params[i].value);"
else:
print >> out, " static char* kwlist[] = { NULL };";
print >> out
if constructor.deprecated is not None:
print >> out, ' if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\
constructor.deprecated
print >> out, ' return -1;'
print >> out
print >> out, ' if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":%s.__init__", kwlist))' % classname
print >> out, " return -1;"
print >> out
print >> out, " self->obj = g_object_newv(obj_type, 0, NULL);"
print >> out, \
' if (!self->obj) {\n' \
' PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \
' return -1;\n' \
' }\n'
if not constructor.caller_owns_return:
print >> out, " g_object_ref(self->obj);\n"
print >> out, \
' pygobject_register_wrapper((PyObject *)self);\n' \
' return 0;\n' \
'}\n\n' % { 'typename': classname }
return "_wrap_%s" % constructor.c_name
## TODO : Add GstMiniObjectWrapper(Wrapper) ## TODO : Add GstMiniObjectWrapper(Wrapper)
class GstMiniObjectWrapper(Wrapper): class GstMiniObjectWrapper(Wrapper):
@ -615,6 +888,70 @@ class GInterfaceWrapper(GObjectWrapper):
# interfaces have no fields ... # interfaces have no fields ...
return '0' return '0'
def write_virtual_accessors(self):
## we don't want the 'chaining' functions for interfaces
return []
def write_virtuals(self):
## Now write reverse method wrappers, which let python code
## implement interface methods.
# First, get methods from the defs files
klass = self.objinfo.c_name
proxies = []
for meth in self.parser.find_virtuals(self.objinfo):
method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
if self.overrides.is_ignored(method_name):
continue
try:
if self.overrides.is_overriden(method_name):
if not self.overrides.is_already_included(method_name):
data = self.overrides.override(method_name)
self.write_function(method_name, data)
else:
# write proxy ...
ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
wrapper = reversewrapper.ReverseWrapper(
'_wrap_' + method_name, is_static=True)
wrapper.set_return_type(ret(wrapper, **props))
wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
wrapper, "self", method_name="do_" + meth.name,
c_type=(klass + ' *')))
for param in meth.params:
handler, props = argtypes.matcher.get_reverse(param.ptype)
wrapper.add_parameter(handler(wrapper, param.pname, **props))
buf = reversewrapper.MemoryCodeSink()
wrapper.generate(buf)
self.fp.write(buf.flush())
proxies.append((fixname(meth.name), '_wrap_' + method_name))
iproxies_coverage.declare_wrapped()
except KeyError:
iproxies_coverage.declare_not_wrapped()
proxies.append((fixname(meth.name), None))
sys.stderr.write('Could not write interface proxy %s.%s: %s\n'
% (klass, meth.name, exc_info()))
if proxies:
## Write an interface init function for this object
funcname = "__%s__interface_init" % klass
vtable = self.objinfo.vtable
self.fp.write(('\nstatic void\n'
'%(funcname)s(%(vtable)s *iface)\n'
'{\n') % vars())
for name, cname in proxies:
do_name = 'do_' + name
if cname is not None:
self.fp.write(' iface->%s = %s;\n' % (name, cname))
self.fp.write('}\n\n')
interface_info = "__%s__iinfo" % klass
self.fp.write('''
static const GInterfaceInfo %s = {
(GInterfaceInitFunc) %s,
NULL,
NULL
};
''' % (interface_info, funcname))
self.objinfo.interface_info = interface_info
class GBoxedWrapper(Wrapper): class GBoxedWrapper(Wrapper):
constructor_tmpl = \ constructor_tmpl = \
'static int\n' \ 'static int\n' \
@ -702,7 +1039,7 @@ class GPointerWrapper(GBoxedWrapper):
return substdict return substdict
def write_headers(data, fp): def write_headers(data, fp):
fp.write('/* -- THIS FILE IS GENERATE - DO NOT EDIT */') fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */')
fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n') fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
fp.write('#include <Python.h>\n\n\n') fp.write('#include <Python.h>\n\n\n')
fp.write(data) fp.write(data)
@ -751,15 +1088,17 @@ def write_enums(parser, prefix, fp=sys.stdout):
% (value, value)) % (value, value))
else: else:
if enum.deftype == 'enum': if enum.deftype == 'enum':
fp.write(' pyg_enum_add_constants(module, %s, strip_prefix);\n' fp.write(' pyg_enum_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
% (enum.typecode,))
else: else:
fp.write(' pyg_flags_add_constants(module, %s, strip_prefix);\n' fp.write(' pyg_flags_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
% (enum.typecode,))
fp.write('\n')
fp.write(' if (PyErr_Occurred())\n')
fp.write(' PyErr_Print();\n')
fp.write('}\n\n') fp.write('}\n\n')
def write_extension_init(overrides, prefix, fp): def write_extension_init(overrides, prefix, fp):
fp.write('/* intialise stuff extension classes */\n') fp.write('/* initialise stuff extension classes */\n')
fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n') fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n')
imports = overrides.get_imports()[:] imports = overrides.get_imports()[:]
if imports: if imports:
@ -798,6 +1137,9 @@ def write_registers(parser, fp):
fp.write(' pyg_register_interface(d, "' + interface.name + fp.write(' pyg_register_interface(d, "' + interface.name +
'", '+ interface.typecode + ', &Py' + interface.c_name + '", '+ interface.typecode + ', &Py' + interface.c_name +
'_Type);\n') '_Type);\n')
if interface.interface_info is not None:
fp.write(' pyg_register_interface_info(%s, &%s);\n' %
(interface.typecode, interface.interface_info))
objects = parser.objects[:] objects = parser.objects[:]
pos = 0 pos = 0
@ -825,6 +1167,9 @@ def write_registers(parser, fp):
fp.write(' pygobject_register_class(d, "' + obj.c_name + fp.write(' pygobject_register_class(d, "' + obj.c_name +
'", ' + obj.typecode + ', &Py' + obj.c_name + '", ' + obj.typecode + ', &Py' + obj.c_name +
'_Type, NULL);\n') '_Type, NULL);\n')
if obj.class_init_func is not None:
fp.write(' pyg_register_class_init(%s, %s);\n' %
(obj.typecode, obj.class_init_func))
#TODO: register mini-objects #TODO: register mini-objects
miniobjects = parser.miniobjects[:] miniobjects = parser.miniobjects[:]
for obj in miniobjects: for obj in miniobjects:
@ -917,9 +1262,17 @@ def main(argv):
p = defsparser.DefsParser(args[0], defines) p = defsparser.DefsParser(args[0], defines)
if not outfilename: if not outfilename:
outfilename = os.path.splitext(args[0])[0] + '.c' outfilename = os.path.splitext(args[0])[0] + '.c'
p.startParsing() p.startParsing()
register_types(p) register_types(p)
write_source(p, o, prefix, FileOutput(sys.stdout, outfilename)) write_source(p, o, prefix, FileOutput(sys.stdout, outfilename))
functions_coverage.printstats()
methods_coverage.printstats()
vproxies_coverage.printstats()
vaccessors_coverage.printstats()
iproxies_coverage.printstats()
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main(sys.argv)) sys.exit(main(sys.argv))

View file

@ -1,5 +1,41 @@
# -*- Mode: Python; py-indent-offset: 4 -*- # -*- Mode: Python; py-indent-offset: 4 -*-
import sys import sys
from copy import *
def get_valid_scheme_definitions(defs):
return [x for x in defs if isinstance(x, tuple) and len(x) >= 2]
# New Parameter class, wich emulates a tuple for compatibility reasons
class Parameter(object):
def __init__(self, ptype, pname, pdflt, pnull, prop=None):
self.ptype = ptype
self.pname = pname
self.pdflt = pdflt
self.pnull = pnull
def __len__(self): return 4
def __getitem__(self, i):
return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
def merge(self, old):
if old.pdflt is not None:
self.pdflt = old.pdflt
if old.pnull is not None:
self.pnull = old.pnull
# Parameter for property based constructors
class Property(object):
def __init__(self, pname, optional, argname):
self.pname = pname
self.optional = optional
self.argname = argname
def merge(self, old):
if old.optional is not None:
self.optional = old.optional
if old.argname is not None:
self.argname = old.argname
class Definition: class Definition:
def __init__(self, *args): def __init__(self, *args):
@ -13,6 +49,16 @@ class Definition:
"""write out this definition in defs file format""" """write out this definition in defs file format"""
raise RuntimeError, "this is an abstract class" raise RuntimeError, "this is an abstract class"
def guess_return_value_ownership(self):
"return 1 if caller owns return value"
if getattr(self, 'is_constructor_of', False):
self.caller_owns_return = True
elif self.ret in ('char*', 'gchar*', 'string'):
self.caller_owns_return = True
else:
self.caller_owns_return = False
class ObjectDef(Definition): class ObjectDef(Definition):
def __init__(self, name, *args): def __init__(self, name, *args):
self.name = name self.name = name
@ -22,9 +68,8 @@ class ObjectDef(Definition):
self.typecode = None self.typecode = None
self.fields = [] self.fields = []
self.implements = [] self.implements = []
for arg in args: self.class_init_func = None
if type(arg) != type(()) or len(arg) < 2: for arg in get_valid_scheme_definitions(args):
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.module = arg[1] self.module = arg[1]
elif arg[0] == 'parent': elif arg[0] == 'parent':
@ -120,16 +165,20 @@ class InterfaceDef(Definition):
self.module = None self.module = None
self.c_name = None self.c_name = None
self.typecode = None self.typecode = None
self.vtable = None
self.fields = [] self.fields = []
for arg in args: self.interface_info = None
if type(arg) != type(()) or len(arg) < 2: for arg in get_valid_scheme_definitions(args):
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.module = arg[1] self.module = arg[1]
elif arg[0] == 'c-name': elif arg[0] == 'c-name':
self.c_name = arg[1] self.c_name = arg[1]
elif arg[0] == 'gtype-id': elif arg[0] == 'gtype-id':
self.typecode = arg[1] self.typecode = arg[1]
elif arg[0] == 'vtable':
self.vtable = arg[1]
if self.vtable is None:
self.vtable = self.c_name + "Iface"
def write_defs(self, fp=sys.stdout): def write_defs(self, fp=sys.stdout):
fp.write('(define-interface ' + self.name + '\n') fp.write('(define-interface ' + self.name + '\n')
if self.module: if self.module:
@ -148,9 +197,7 @@ class EnumDef(Definition):
self.c_name = None self.c_name = None
self.typecode = None self.typecode = None
self.values = [] self.values = []
for arg in args: for arg in get_valid_scheme_definitions(args):
if type(arg) != type(()) or len(arg) < 2:
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.in_module = arg[1] self.in_module = arg[1]
elif arg[0] == 'c-name': elif arg[0] == 'c-name':
@ -189,9 +236,7 @@ class BoxedDef(Definition):
self.copy = None self.copy = None
self.release = None self.release = None
self.fields = [] self.fields = []
for arg in args: for arg in get_valid_scheme_definitions(args):
if type(arg) != type(()) or len(arg) < 2:
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.module = arg[1] self.module = arg[1]
elif arg[0] == 'c-name': elif arg[0] == 'c-name':
@ -236,9 +281,7 @@ class PointerDef(Definition):
self.c_name = None self.c_name = None
self.typecode = None self.typecode = None
self.fields = [] self.fields = []
for arg in args: for arg in get_valid_scheme_definitions(args):
if type(arg) != type(()) or len(arg) < 2:
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.module = arg[1] self.module = arg[1]
elif arg[0] == 'c-name': elif arg[0] == 'c-name':
@ -268,7 +311,7 @@ class PointerDef(Definition):
fp.write(' )\n') fp.write(' )\n')
fp.write(')\n\n') fp.write(')\n\n')
class MethodDef(Definition): class MethodDefBase(Definition):
def __init__(self, name, *args): def __init__(self, name, *args):
dump = 0 dump = 0
self.name = name self.name = name
@ -280,9 +323,7 @@ class MethodDef(Definition):
self.params = [] # of form (type, name, default, nullok) self.params = [] # of form (type, name, default, nullok)
self.varargs = 0 self.varargs = 0
self.deprecated = None self.deprecated = None
for arg in args: for arg in get_valid_scheme_definitions(args):
if type(arg) != type(()) or len(arg) < 2:
continue
if arg[0] == 'of-object': if arg[0] == 'of-object':
self.of_object = arg[1] self.of_object = arg[1]
elif arg[0] == 'c-name': elif arg[0] == 'c-name':
@ -300,11 +341,12 @@ class MethodDef(Definition):
pdflt = None pdflt = None
pnull = 0 pnull = 0
for farg in parg[2:]: for farg in parg[2:]:
assert isinstance(farg, tuple)
if farg[0] == 'default': if farg[0] == 'default':
pdflt = farg[1] pdflt = farg[1]
elif farg[0] == 'null-ok': elif farg[0] == 'null-ok':
pnull = 1 pnull = 1
self.params.append((ptype, pname, pdflt, pnull)) self.params.append(Parameter(ptype, pname, pdflt, pnull))
elif arg[0] == 'varargs': elif arg[0] == 'varargs':
self.varargs = arg[1] in ('t', '#t') self.varargs = arg[1] in ('t', '#t')
elif arg[0] == 'deprecated': elif arg[0] == 'deprecated':
@ -317,33 +359,30 @@ class MethodDef(Definition):
self.write_defs(sys.stderr) self.write_defs(sys.stderr)
if self.caller_owns_return is None and self.ret is not None: if self.caller_owns_return is None and self.ret is not None:
if self.ret[:6] == 'const-': self.guess_return_value_ownership()
self.caller_owns_return = 0
elif self.ret in ('char*', 'gchar*', 'string'):
self.caller_owns_return = 1
else:
self.caller_owns_return = 0
for item in ('c_name', 'of_object'):
if self.__dict__[item] == None:
self.write_defs(sys.stderr)
raise RuntimeError, "definition missing required %s" % (item,)
def merge(self, old): def merge(self, old, parmerge):
self.caller_owns_return = old.caller_owns_return
self.varargs = old.varargs
# here we merge extra parameter flags accross to the new object. # here we merge extra parameter flags accross to the new object.
if not parmerge:
self.params = deepcopy(old.params)
return
for i in range(len(self.params)): for i in range(len(self.params)):
ptype, pname, pdflt, pnull = self.params[i] ptype, pname, pdflt, pnull = self.params[i]
for p2 in old.params: for p2 in old.params:
if p2[1] == pname: if p2[1] == pname:
self.params[i] = (ptype, pname, p2[2], p2[3]) self.params[i] = (ptype, pname, p2[2], p2[3])
break break
def write_defs(self, fp=sys.stdout): def _write_defs(self, fp=sys.stdout):
fp.write('(define-method ' + self.name + '\n')
if self.of_object != (None, None): if self.of_object != (None, None):
fp.write(' (of-object "' + self.of_object + '")\n') fp.write(' (of-object "' + self.of_object + '")\n')
if self.c_name: if self.c_name:
fp.write(' (c-name "' + self.c_name + '")\n') fp.write(' (c-name "' + self.c_name + '")\n')
if self.typecode: if self.typecode:
fp.write(' (gtype-id "' + self.typecode + '")\n') fp.write(' (gtype-id "' + self.typecode + '")\n')
if self.caller_owns_return:
fp.write(' (caller-owns-return #t)\n')
if self.ret: if self.ret:
fp.write(' (return-type "' + self.ret + '")\n') fp.write(' (return-type "' + self.ret + '")\n')
if self.deprecated: if self.deprecated:
@ -356,8 +395,27 @@ class MethodDef(Definition):
if pnull: fp.write(' (null-ok)') if pnull: fp.write(' (null-ok)')
fp.write(')\n') fp.write(')\n')
fp.write(' )\n') fp.write(' )\n')
if self.varargs:
fp.write(' (varargs #t)\n')
fp.write(')\n\n') fp.write(')\n\n')
class MethodDef(MethodDefBase):
def __init__(self, name, *args):
MethodDefBase.__init__(self, name, *args)
for item in ('c_name', 'of_object'):
if self.__dict__[item] == None:
self.write_defs(sys.stderr)
raise RuntimeError, "definition missing required %s" % (item,)
def write_defs(self, fp=sys.stdout):
fp.write('(define-method ' + self.name + '\n')
self._write_defs(fp)
class VirtualDef(MethodDefBase):
def write_defs(self, fp=sys.stdout):
fp.write('(define-virtual ' + self.name + '\n')
self._write_defs(fp)
class FunctionDef(Definition): class FunctionDef(Definition):
def __init__(self, name, *args): def __init__(self, name, *args):
dump = 0 dump = 0
@ -371,9 +429,7 @@ class FunctionDef(Definition):
self.params = [] # of form (type, name, default, nullok) self.params = [] # of form (type, name, default, nullok)
self.varargs = 0 self.varargs = 0
self.deprecated = None self.deprecated = None
for arg in args: for arg in get_valid_scheme_definitions(args):
if type(arg) != type(()) or len(arg) < 2:
continue
if arg[0] == 'in-module': if arg[0] == 'in-module':
self.in_module = arg[1] self.in_module = arg[1]
elif arg[0] == 'is-constructor-of': elif arg[0] == 'is-constructor-of':
@ -397,7 +453,21 @@ class FunctionDef(Definition):
pdflt = farg[1] pdflt = farg[1]
elif farg[0] == 'null-ok': elif farg[0] == 'null-ok':
pnull = 1 pnull = 1
self.params.append((ptype, pname, pdflt, pnull)) self.params.append(Parameter(ptype, pname, pdflt, pnull))
elif arg[0] == 'properties':
if self.is_constructor_of is None:
print >> sys.stderr, "Warning: (properties ...) "\
"is only valid for constructors"
for prop in arg[1:]:
pname = prop[0]
optional = False
argname = pname
for farg in prop[1:]:
if farg[0] == 'optional':
optional = True
elif farg[0] == 'argname':
argname = farg[1]
self.params.append(Property(pname, optional, argname))
elif arg[0] == 'varargs': elif arg[0] == 'varargs':
self.varargs = arg[1] in ('t', '#t') self.varargs = arg[1] in ('t', '#t')
elif arg[0] == 'deprecated': elif arg[0] == 'deprecated':
@ -410,14 +480,7 @@ class FunctionDef(Definition):
self.write_defs(sys.stderr) self.write_defs(sys.stderr)
if self.caller_owns_return is None and self.ret is not None: if self.caller_owns_return is None and self.ret is not None:
if self.ret[:6] == 'const-': self.guess_return_value_ownership()
self.caller_owns_return = 0
elif self.is_constructor_of:
self.caller_owns_return = 1
elif self.ret in ('char*', 'gchar*', 'string'):
self.caller_owns_return = 1
else:
self.caller_owns_return = 0
for item in ('c_name',): for item in ('c_name',):
if self.__dict__[item] == None: if self.__dict__[item] == None:
self.write_defs(sys.stderr) self.write_defs(sys.stderr)
@ -425,14 +488,33 @@ class FunctionDef(Definition):
_method_write_defs = MethodDef.__dict__['write_defs'] _method_write_defs = MethodDef.__dict__['write_defs']
def merge(self, old): def merge(self, old, parmerge):
self.caller_owns_return = old.caller_owns_return
self.varargs = old.varargs
if not parmerge:
self.params = deepcopy(old.params)
return
# here we merge extra parameter flags accross to the new object. # here we merge extra parameter flags accross to the new object.
for i in range(len(self.params)): def merge_param(param):
ptype, pname, pdflt, pnull = self.params[i] for old_param in old.params:
for p2 in old.params: if old_param.pname == param.pname:
if p2[1] == pname: if isinstance(old_param, Property):
self.params[i] = (ptype, pname, p2[2], p2[3]) # h2def never scans Property's, therefore if
break # we have one it was manually written, so we
# keep it.
return deepcopy(old_param)
else:
param.merge(old_param)
return param
raise RuntimeError, "could not find %s in old_parameters %r" % (
param.pname, [p.pname for p in old.params])
try:
self.params = map(merge_param, self.params)
except RuntimeError:
# parameter names changed and we can't find a match; it's
# safer to keep the old parameter list untouched.
self.params = deepcopy(old.params)
if not self.is_constructor_of: if not self.is_constructor_of:
try: try:
self.is_constructor_of = old.is_constructor_of self.is_constructor_of = old.is_constructor_of
@ -454,17 +536,31 @@ class FunctionDef(Definition):
fp.write(' (c-name "' + self.c_name + '")\n') fp.write(' (c-name "' + self.c_name + '")\n')
if self.typecode: if self.typecode:
fp.write(' (gtype-id "' + self.typecode + '")\n') fp.write(' (gtype-id "' + self.typecode + '")\n')
if self.caller_owns_return:
fp.write(' (caller-owns-return #t)\n')
if self.ret: if self.ret:
fp.write(' (return-type "' + self.ret + '")\n') fp.write(' (return-type "' + self.ret + '")\n')
if self.deprecated: if self.deprecated:
fp.write(' (deprecated "' + self.deprecated + '")\n') fp.write(' (deprecated "' + self.deprecated + '")\n')
if self.params: if self.params:
fp.write(' (parameters\n') if isinstance(self.params[0], Parameter):
for ptype, pname, pdflt, pnull in self.params: fp.write(' (parameters\n')
fp.write(' \'("' + ptype + '" "' + pname +'"') for ptype, pname, pdflt, pnull in self.params:
if pdflt: fp.write(' (default "' + pdflt + '")') fp.write(' \'("' + ptype + '" "' + pname +'"')
if pnull: fp.write(' (null-ok)') if pdflt: fp.write(' (default "' + pdflt + '")')
fp.write(')\n') if pnull: fp.write(' (null-ok)')
fp.write(' )\n') fp.write(')\n')
fp.write(')\n\n') fp.write(' )\n')
elif isinstance(self.params[0], Property):
fp.write(' (properties\n')
for prop in self.params:
fp.write(' \'("' + prop.pname +'"')
if prop.optional: fp.write(' (optional)')
fp.write(')\n')
fp.write(' )\n')
else:
assert False, "strange parameter list %r" % self.params[0]
if self.varargs:
fp.write(' (varargs #t)\n')
fp.write(')\n\n')

View file

@ -25,6 +25,7 @@ class DefsParser(IncludeParser):
self.boxes = [] # boxed types self.boxes = [] # boxed types
self.pointers = [] # pointer types self.pointers = [] # pointer types
self.functions = [] # functions and methods self.functions = [] # functions and methods
self.virtuals = [] # virtual methods
self.c_name = {} # hash of c names of functions self.c_name = {} # hash of c names of functions
self.methods = {} # hash of methods of particular objects self.methods = {} # hash of methods of particular objects
self.defines = defines # -Dfoo=bar options, as dictionary self.defines = defines # -Dfoo=bar options, as dictionary
@ -66,13 +67,17 @@ class DefsParser(IncludeParser):
mdef = apply(MethodDef, args) mdef = apply(MethodDef, args)
self.functions.append(mdef) self.functions.append(mdef)
self.c_name[mdef.c_name] = mdef self.c_name[mdef.c_name] = mdef
def merge(self, old): def define_virtual(self, *args):
vdef = apply(VirtualDef, args)
self.virtuals.append(vdef)
def merge(self, old, parmerge):
for obj in self.objects: for obj in self.objects:
if old.c_name.has_key(obj.c_name): if old.c_name.has_key(obj.c_name):
obj.merge(old.c_name[obj.c_name]) obj.merge(old.c_name[obj.c_name])
for f in self.functions: for f in self.functions:
if old.c_name.has_key(f.c_name): if old.c_name.has_key(f.c_name):
f.merge(old.c_name[f.c_name]) f.merge(old.c_name[f.c_name], parmerge)
def printMissing(self, old): def printMissing(self, old):
for obj in self.objects: for obj in self.objects:
if not old.c_name.has_key(obj.c_name): if not old.c_name.has_key(obj.c_name):
@ -115,6 +120,12 @@ class DefsParser(IncludeParser):
return filter(lambda func, on=objname: isinstance(func, MethodDef) and return filter(lambda func, on=objname: isinstance(func, MethodDef) and
func.of_object == on, self.functions) func.of_object == on, self.functions)
def find_virtuals(self, obj):
objname = obj.c_name
retval = filter(lambda func, on=objname: isinstance(func, VirtualDef) and
func.of_object == on, self.virtuals)
return retval
def find_functions(self): def find_functions(self):
return filter(lambda func: isinstance(func, FunctionDef) and return filter(lambda func: isinstance(func, FunctionDef) and
not func.is_constructor_of, self.functions) not func.is_constructor_of, self.functions)

View file

@ -53,7 +53,7 @@ def strip_comments(buf):
obj_name_pat = "[A-Z][a-z]*[A-Z][A-Za-z0-9]*" obj_name_pat = "[A-Z][a-z]*[A-Z][A-Za-z0-9]*"
split_prefix_pat = re.compile('([A-Z][a-z]*)([A-Za-z0-9]+)') split_prefix_pat = re.compile('([A-Z]+[a-z]*)([A-Za-z0-9]+)')
def find_obj_defs(buf, objdefs=[]): def find_obj_defs(buf, objdefs=[]):
""" """
@ -312,7 +312,7 @@ proto_pat=re.compile(r"""
(?P<ret>(-|\w|\&|\*)+\s*) # return type (?P<ret>(-|\w|\&|\*)+\s*) # return type
\s+ # skip whitespace \s+ # skip whitespace
(?P<func>\w+)\s*[(] # match the function name until the opening ( (?P<func>\w+)\s*[(] # match the function name until the opening (
(?P<args>.*?)[)] # group the function arguments \s*(?P<args>.*?)[)] # group the function arguments
""", re.IGNORECASE|re.VERBOSE) """, re.IGNORECASE|re.VERBOSE)
#""" #"""
arg_split_pat = re.compile("\s*,\s*") arg_split_pat = re.compile("\s*,\s*")
@ -353,7 +353,7 @@ def write_func(fp, name, ret, args, prefix):
obj = m.group(2) obj = m.group(2)
if munged_name[:len(obj)] == string.lower(obj): if munged_name[:len(obj)] == string.lower(obj):
regex = string.join(map(lambda x: x+'_?',string.lower(obj)),'') regex = string.join(map(lambda x: x+'_?',string.lower(obj)),'')
mname = re.sub(regex, '', name) mname = re.sub(regex, '', name, 1)
if prefix: if prefix:
l = len(prefix) + 1 l = len(prefix) + 1
if mname[:l] == prefix and mname[l+1] == '_': if mname[:l] == prefix and mname[l+1] == '_':

View file

@ -3,17 +3,23 @@
import sys import sys
import defsparser import defsparser
from optparse import OptionParser
if len(sys.argv) < 3: parser = OptionParser(usage="usage: %prog [options] generated-defs old-defs")
sys.stderr.write("Usage: mergedefs.py generated-defs old-defs\n") parser.add_option("-p", "--merge-parameters",
sys.exit(1) help="Merge changes in function/methods parameter lists",
action="store_true", dest="parmerge", default=False)
(options, args) = parser.parse_args()
newp = defsparser.DefsParser(sys.argv[1]) if len(args) != 2:
oldp = defsparser.DefsParser(sys.argv[2]) parser.error("wrong number of arguments")
newp = defsparser.DefsParser(args[0])
oldp = defsparser.DefsParser(args[1])
newp.startParsing() newp.startParsing()
oldp.startParsing() oldp.startParsing()
newp.merge(oldp) newp.merge(oldp, options.parmerge)
newp.write_defs() newp.write_defs()

667
codegen/reversewrapper.py Normal file
View file

@ -0,0 +1,667 @@
### -*- python -*-
### Code to generate "Reverse Wrappers", i.e. C->Python wrappers
### (C) 2004 Gustavo Carneiro <gjc@gnome.org>
import argtypes
def join_ctype_name(ctype, name):
'''Joins a C type and a variable name into a single string'''
if ctype[-1] != '*':
return " ".join((ctype, name))
else:
return "".join((ctype, name))
class CodeSink(object):
def __init__(self):
self.indent_level = 0 # current indent level
self.indent_stack = [] # previous indent levels
def _format_code(self, code):
assert isinstance(code, str)
l = []
for line in code.split('\n'):
l.append(' '*self.indent_level + line)
if l[-1]:
l.append('')
return '\n'.join(l)
def writeln(self, line=''):
raise NotImplementedError
def indent(self, level=4):
'''Add a certain ammount of indentation to all lines written
from now on and until unindent() is called'''
self.indent_stack.append(self.indent_level)
self.indent_level += level
def unindent(self):
'''Revert indentation level to the value before last indent() call'''
self.indent_level = self.indent_stack.pop()
class FileCodeSink(CodeSink):
def __init__(self, fp):
CodeSink.__init__(self)
assert isinstance(fp, file)
self.fp = fp
def writeln(self, line=''):
self.fp.write(self._format_code(line))
class MemoryCodeSink(CodeSink):
def __init__(self):
CodeSink.__init__(self)
self.lines = []
def writeln(self, line=''):
self.lines.append(self._format_code(line))
def flush_to(self, sink):
assert isinstance(sink, CodeSink)
for line in self.lines:
sink.writeln(line.rstrip())
self.lines = []
def flush(self):
l = []
for line in self.lines:
l.append(self._format_code(line))
self.lines = []
return "".join(l)
class ReverseWrapper(object):
'''Object that generates a C->Python wrapper'''
def __init__(self, cname, is_static=True):
assert isinstance(cname, str)
self.cname = cname
## function object we will call, or object whose method we will call
self.called_pyobj = None
## name of method of self.called_pyobj we will call
self.method_name = None
self.is_static = is_static
self.parameters = []
self.declarations = MemoryCodeSink()
self.body = MemoryCodeSink()
self.cleanup_actions = []
self.pyargv_items = []
self.pyargv_optional_items = []
def set_call_target(self, called_pyobj, method_name=None):
assert called_pyobj is not None
assert self.called_pyobj is None
self.called_pyobj = called_pyobj
self.method_name = method_name
def set_return_type(self, return_type):
assert isinstance(return_type, ReturnType)
self.return_type = return_type
def add_parameter(self, param):
assert isinstance(param, Parameter)
self.parameters.append(param)
def add_declaration(self, decl_code):
self.declarations.writeln(decl_code)
def add_pyargv_item(self, variable, optional=False):
if optional:
self.pyargv_optional_items.append(variable)
else:
self.pyargv_items.append(variable)
def write_code(self, code,
cleanup=None,
failure_expression=None,
failure_cleanup=None):
'''Add a chunk of code with cleanup and error handling
This method is to be used by TypeHandlers when generating code
Keywork arguments:
code -- code to add
cleanup -- code to cleanup any dynamic resources created by @code
(except in case of failure) (default None)
failure_expression -- C boolean expression to indicate
if anything failed (default None)
failure_cleanup -- code to cleanup any dynamic resources
created by @code in case of failure (default None)
'''
if code is not None:
self.body.writeln(code)
if failure_expression is not None:
self.body.writeln("if (%s) {" % failure_expression)
self.body.indent()
self.body.writeln("if (PyErr_Occurred())")
self.body.indent()
self.body.writeln("PyErr_Print();")
self.body.unindent()
if failure_cleanup is not None:
self.body.writeln(failure_cleanup)
for cleanup_action in self.cleanup_actions:
self.body.writeln(cleanup_action)
self.return_type.write_error_return()
self.body.unindent()
self.body.writeln("}")
if cleanup is not None:
self.cleanup_actions.insert(0, cleanup)
def generate(self, sink):
'''Generate the code into a CodeSink object'''
assert isinstance(sink, CodeSink)
self.add_declaration("PyGILState_STATE __py_state;")
self.write_code(code="__py_state = pyg_gil_state_ensure();",
cleanup="pyg_gil_state_release(__py_state);")
for param in self.parameters:
param.convert_c2py()
assert self.called_pyobj is not None,\
"Parameters failed to provide a target function or method."
if self.is_static:
sink.writeln('static %s' % self.return_type.get_c_type())
else:
sink.writeln(self.return_type.get_c_type())
c_proto_params = map(Parameter.format_for_c_proto, self.parameters)
sink.writeln("%s(%s)\n{" % (self.cname, ", ".join(c_proto_params)))
self.return_type.write_decl()
self.add_declaration("PyObject *py_retval;")
## Handle number of arguments
if self.pyargv_items:
self.add_declaration("PyObject *py_args;")
py_args = "py_args"
if self.pyargv_optional_items:
self.add_declaration("int argc = %i;" % len(self.pyargv_items))
argc = "argc"
for arg in self.pyargv_optional_items:
self.body.writeln("if (%s)" % arg)
self.body.indent()
self.body.writeln("++argc;")
self.body.unindent()
else:
argc = str(len(self.pyargv_items))
else:
if self.pyargv_optional_items:
self.add_declaration("PyObject *py_args;")
py_args = "py_args"
self.add_declaration("int argc = 0;")
argc = "argc"
for arg in self.pyargv_optional_items:
self.body.writeln("if (%s)" % arg)
self.body.indent()
self.body.writeln("++argc;")
self.body.unindent()
else:
py_args = "NULL"
argc = None
self.body.writeln()
if py_args != "NULL":
self.write_code("py_args = PyTuple_New(%s);" % argc,
cleanup="Py_DECREF(py_args);")
pos = 0
for arg in self.pyargv_items:
try: # try to remove the Py_DECREF cleanup action, if we can
self.cleanup_actions.remove("Py_DECREF(%s);" % arg)
except ValueError: # otherwise we have to Py_INCREF..
self.body.writeln("Py_INCREF(%s);" % arg)
self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
pos += 1
for arg in self.pyargv_optional_items:
self.body.writeln("if (%s) {" % arg)
self.body.indent()
try: # try to remove the Py_DECREF cleanup action, if we can
self.cleanup_actions.remove("Py_XDECREF(%s);" % arg)
except ValueError: # otherwise we have to Py_INCREF..
self.body.writeln("Py_INCREF(%s);" % arg)
self.body.writeln("PyTuple_SET_ITEM(%s, %i, %s);" % (py_args, pos, arg))
self.body.unindent()
self.body.writeln("}")
pos += 1
self.body.writeln()
# call it
if self.method_name is None:
self.write_code("py_retval = PyObject_Call(%s, %s);"
% (self.called_pyobj, py_args),
cleanup="Py_DECREF(py_retval);",
failure_expression="!py_retval")
else:
self.add_declaration("PyObject *py_method;")
self.write_code("py_method = PyObject_GetAttrString(%s, \"%s\");"
% (self.called_pyobj, self.method_name),
cleanup="Py_DECREF(py_method);",
failure_expression="!py_method")
self.write_code("py_retval = PyObject_CallObject(py_method, %s);"
% (py_args,),
cleanup="Py_DECREF(py_retval);",
failure_expression="!py_retval")
self.return_type.write_conversion()
sink.indent()
self.declarations.flush_to(sink)
sink.writeln()
self.body.flush_to(sink)
sink.writeln()
for cleanup_action in self.cleanup_actions:
sink.writeln(cleanup_action)
if self.return_type.get_c_type() != 'void':
sink.writeln()
sink.writeln("return retval;")
sink.unindent()
sink.writeln("}")
class TypeHandler(object):
def __init__(self, wrapper, **props):
assert isinstance(wrapper, ReverseWrapper)
self.wrapper = wrapper
self.props = props
class ReturnType(TypeHandler):
def get_c_type(self):
raise NotImplementedError
def write_decl(self):
raise NotImplementedError
def write_error_return(self):
'''Write "return <value>" code in case of error'''
raise NotImplementedError
def write_conversion(self):
'''Writes code to convert Python return value in 'py_retval'
into C 'retval'. Returns a string with C boolean expression
that determines if anything went wrong. '''
raise NotImplementedError
class Parameter(TypeHandler):
def __init__(self, wrapper, name, **props):
TypeHandler.__init__(self, wrapper, **props)
self.name = name
def get_c_type(self):
raise NotImplementedError
def convert_c2py(self):
'''Write some code before calling the Python method.'''
pass
def format_for_c_proto(self):
return join_ctype_name(self.get_c_type(), self.name)
###---
class StringParam(Parameter):
def get_c_type(self):
return self.props.get('c_type', 'char *').replace('const-', 'const ')
def convert_c2py(self):
if self.props.get('optional', False):
self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
self.wrapper.write_code(code=("if (%s)\n"
" py_%s = PyString_FromString(%s);\n"
% (self.name, self.name, self.name)),
cleanup=("Py_XDECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name, optional=True)
else:
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = PyString_FromString(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
for ctype in ('char*', 'gchar*', 'const-char*', 'char-const*', 'const-gchar*',
'gchar-const*', 'string', 'static_string'):
argtypes.matcher.register_reverse(ctype, StringParam)
class StringReturn(ReturnType):
def get_c_type(self):
return "char *"
def write_decl(self):
self.wrapper.add_declaration("char *retval;")
def write_error_return(self):
self.wrapper.write_code("return NULL;")
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression="!PyString_Check(py_retval)",
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a string");')
self.wrapper.write_code("retval = g_strdup(PyString_AsString(py_retval));")
for ctype in ('char*', 'gchar*'):
argtypes.matcher.register_reverse(ctype, StringReturn)
class VoidReturn(ReturnType):
def get_c_type(self):
return "void"
def write_decl(self):
pass
def write_error_return(self):
self.wrapper.write_code("return;")
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression="py_retval != Py_None",
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be None");')
argtypes.matcher.register_reverse_ret('void', VoidReturn)
argtypes.matcher.register_reverse_ret('none', VoidReturn)
class GObjectParam(Parameter):
def get_c_type(self):
return self.props.get('c_type', 'GObject *')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s = NULL;" % self.name)
self.wrapper.write_code(code=("if (%s)\n"
" py_%s = pygobject_new((GObject *) %s);\n"
"else {\n"
" Py_INCREF(Py_None);\n"
" py_%s = Py_None;\n"
"}"
% (self.name, self.name, self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse('GObject*', GObjectParam)
class GObjectReturn(ReturnType):
def get_c_type(self):
return self.props.get('c_type', 'GObject *')
def write_decl(self):
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
def write_error_return(self):
self.wrapper.write_code("return NULL;")
def write_conversion(self):
self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
% self.get_c_type())
self.wrapper.write_code("g_object_ref((GObject *) retval);")
argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn)
class IntParam(Parameter):
def get_c_type(self):
return self.props.get('c_type', 'int')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = PyInt_FromLong(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
class IntReturn(ReturnType):
def get_c_type(self):
return self.props.get('c_type', 'int')
def write_decl(self):
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
def write_error_return(self):
self.wrapper.write_code("return -G_MAXINT;")
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression="!PyInt_Check(py_retval)",
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be an int");')
self.wrapper.write_code("retval = PyInt_AsLong(py_retval);")
for argtype in ('int', 'gint', 'guint', 'short', 'gshort', 'gushort', 'long',
'glong', 'gsize', 'gssize', 'guint8', 'gint8', 'guint16',
'gint16', 'gint32', 'GTime'):
argtypes.matcher.register_reverse(argtype, IntParam)
argtypes.matcher.register_reverse_ret(argtype, IntReturn)
class GEnumReturn(IntReturn):
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression=("pyg_enum_get_value(%s, py_retval, (gint *)&retval)" %
self.props['typecode']))
argtypes.matcher.register_reverse_ret("GEnum", GEnumReturn)
class GEnumParam(IntParam):
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = pyg_enum_from_gtype(%s, %s);" %
(self.name, self.props['typecode'], self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("GEnum", GEnumParam)
class GFlagsReturn(IntReturn):
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression=("pyg_flags_get_value(%s, py_retval, (gint *)&retval)" %
self.props['typecode']))
argtypes.matcher.register_reverse_ret("GFlags", GFlagsReturn)
class GFlagsParam(IntParam):
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = pyg_flags_from_gtype(%s, %s);" %
(self.name, self.props['typecode'], self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("GFlags", GFlagsParam)
class GtkTreePathParam(IntParam):
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = pygtk_tree_path_to_pyobject(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("GtkTreePath*", GtkTreePathParam)
class BooleanReturn(ReturnType):
def get_c_type(self):
return "gboolean"
def write_decl(self):
self.wrapper.add_declaration("gboolean retval;")
def write_error_return(self):
self.wrapper.write_code("return FALSE;")
def write_conversion(self):
self.wrapper.write_code("retval = PyObject_IsTrue(py_retval)? TRUE : FALSE;")
argtypes.matcher.register_reverse_ret("gboolean", BooleanReturn)
class BooleanParam(Parameter):
def get_c_type(self):
return "gboolean"
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code("py_%s = %s? Py_True : Py_False;"
% (self.name, self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("gboolean", BooleanParam)
class DoubleParam(Parameter):
def get_c_type(self):
return self.props.get('c_type', 'gdouble')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = PyFloat_FromDouble(%s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
class DoubleReturn(ReturnType):
def get_c_type(self):
return self.props.get('c_type', 'gdouble')
def write_decl(self):
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
def write_error_return(self):
self.wrapper.write_code("return -G_MAXFLOAT;")
def write_conversion(self):
self.wrapper.write_code(
code=None,
failure_expression="!PyFloat_AsDouble(py_retval)",
failure_cleanup='PyErr_SetString(PyExc_TypeError, "retval should be a float");')
self.wrapper.write_code("retval = PyFloat_AsDouble(py_retval);")
for argtype in ('float', 'double', 'gfloat', 'gdouble'):
argtypes.matcher.register_reverse(argtype, DoubleParam)
argtypes.matcher.register_reverse_ret(argtype, DoubleReturn)
class GBoxedParam(Parameter):
def get_c_type(self):
return self.props.get('c_type').replace('const-', 'const ')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
ctype = self.get_c_type()
if ctype.startswith('const '):
ctype_no_const = ctype[len('const '):]
self.wrapper.write_code(
code=('py_%s = pyg_boxed_new(%s, (%s) %s, TRUE, TRUE);' %
(self.name, self.props['typecode'],
ctype_no_const, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
else:
self.wrapper.write_code(
code=('py_%s = pyg_boxed_new(%s, %s, FALSE, FALSE);' %
(self.name, self.props['typecode'], self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("GBoxed", GBoxedParam)
class GBoxedReturn(ReturnType):
def get_c_type(self):
return self.props.get('c_type')
def write_decl(self):
self.wrapper.add_declaration("%s retval;" % self.get_c_type())
def write_error_return(self):
self.wrapper.write_code("return retval;")
def write_conversion(self):
self.wrapper.write_code(
failure_expression=("!pyg_boxed_check(py_retval, %s)" %
(self.props['typecode'],)),
failure_cleanup=('PyErr_SetString(PyExc_TypeError, "retval should be a %s");'
% (self.props['typename'],)))
self.wrapper.write_code('retval = pyg_boxed_get(py_retval, %s);' %
self.props['typename'])
argtypes.matcher.register_reverse_ret("GBoxed", GBoxedReturn)
class GdkRectanglePtrParam(Parameter):
def get_c_type(self):
return self.props.get('c_type').replace('const-', 'const ')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(
code=('py_%(name)s = Py_BuildValue("(ffff)", %(name)s->x, %(name)s->y,\n'
' %(name)s->width, %(name)s->height);'
% dict(name=self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name))
self.wrapper.add_pyargv_item("py_%s" % self.name)
argtypes.matcher.register_reverse("GdkRectangle*", GdkRectanglePtrParam)
class PyGObjectMethodParam(Parameter):
def __init__(self, wrapper, name, method_name, **props):
Parameter.__init__(self, wrapper, name, **props)
self.method_name = method_name
def get_c_type(self):
return self.props.get('c_type', 'GObject *')
def convert_c2py(self):
self.wrapper.add_declaration("PyObject *py_%s;" % self.name)
self.wrapper.write_code(code=("py_%s = pygobject_new((GObject *) %s);" %
(self.name, self.name)),
cleanup=("Py_DECREF(py_%s);" % self.name),
failure_expression=("!py_%s" % self.name))
self.wrapper.set_call_target("py_%s" % self.name, self.method_name)
class CallbackInUserDataParam(Parameter):
def __init__(self, wrapper, name, free_it, **props):
Parameter.__init__(self, wrapper, name, **props)
self.free_it = free_it
def get_c_type(self):
return "gpointer"
def convert_c2py(self):
self.wrapper.add_declaration("PyObject **_user_data;")
cleanup = self.free_it and ("g_free(%s);" % self.name) or None
self.wrapper.write_code(code=("_real_user_data = (PyObject **) %s;"
% self.name),
cleanup=cleanup)
self.wrapper.add_declaration("PyObject *py_func;")
cleanup = self.free_it and "Py_DECREF(py_func);" or None
self.wrapper.write_code(code="py_func = _user_data[0];",
cleanup=cleanup)
self.wrapper.set_call_target("py_func")
self.wrapper.add_declaration("PyObject *py_user_data;")
cleanup = self.free_it and "Py_XDECREF(py_user_data);" or None
self.wrapper.write_code(code="py_user_data = _user_data[1];",
cleanup=cleanup)
self.wrapper.add_pyargv_item("py_user_data", optional=True)
def _test():
import sys
wrapper = ReverseWrapper("this_is_the_c_function_name", is_static=True)
wrapper.set_return_type(StringReturn(wrapper))
wrapper.add_parameter(PyGObjectMethodParam(wrapper, "self", method_name="do_xxx"))
wrapper.add_parameter(StringParam(wrapper, "param2", optional=True))
wrapper.add_parameter(GObjectParam(wrapper, "param3"))
wrapper.generate(FileCodeSink(sys.stderr))
wrapper = ReverseWrapper("this_a_callback_wrapper")
wrapper.set_return_type(VoidReturn(wrapper))
wrapper.add_parameter(StringParam(wrapper, "param1", optional=False))
wrapper.add_parameter(GObjectParam(wrapper, "param2"))
wrapper.add_parameter(CallbackInUserDataParam(wrapper, "data", free_it=True))
wrapper.generate(FileCodeSink(sys.stderr))
if __name__ == '__main__':
_test()

View file

@ -151,6 +151,15 @@
(parent "GstMiniObject") (parent "GstMiniObject")
(c-name "GstBuffer") (c-name "GstBuffer")
(gtype-id "GST_TYPE_BUFFER") (gtype-id "GST_TYPE_BUFFER")
(fields
'("guint8*" "data")
'("guint" "size")
'("GstClockTime" "timestamp")
'("GstClockTime" "duration")
'("GstCaps*" "caps")
'("guint64" "offset")
'("guint64" "offset_end")
)
) )
(define-miniobject Event (define-miniobject Event
@ -158,6 +167,11 @@
(parent "GstMiniObject") (parent "GstMiniObject")
(c-name "GstEvent") (c-name "GstEvent")
(gtype-id "GST_TYPE_EVENT") (gtype-id "GST_TYPE_EVENT")
(fields
'("GstEventType" "type")
'("guint64" "timestamp")
'("GstObject*" "src")
)
) )
(define-miniobject Message (define-miniobject Message
@ -165,6 +179,12 @@
(parent "GstMiniObject") (parent "GstMiniObject")
(c-name "GstMessage") (c-name "GstMessage")
(gtype-id "GST_TYPE_MESSAGE") (gtype-id "GST_TYPE_MESSAGE")
(fields
'("GstMessageType" "type")
'("guint64" "timestamp")
'("GstObject*" "src")
'("GstStructure*" "structure")
)
) )
(define-miniobject Query (define-miniobject Query
@ -172,6 +192,10 @@
(parent "GstMiniObject") (parent "GstMiniObject")
(c-name "GstQuery") (c-name "GstQuery")
(gtype-id "GST_TYPE_QUERY") (gtype-id "GST_TYPE_QUERY")
(fields
'("GstQueryType" "type")
'("GstStructure*" "structure")
)
) )
@ -887,6 +911,7 @@
'("failure" "GST_STATE_FAILURE") '("failure" "GST_STATE_FAILURE")
'("success" "GST_STATE_SUCCESS") '("success" "GST_STATE_SUCCESS")
'("async" "GST_STATE_ASYNC") '("async" "GST_STATE_ASYNC")
'("no-preroll" "GST_STATE_NO_PREROLL")
) )
) )

View file

@ -4416,6 +4416,16 @@
(return-type "gint") (return-type "gint")
) )
(define-method nth_field_name
(of-object "GstStructure")
(c-name "gst_structure_nth_field_name")
(return-type "const-gchar*")
(parameters
'("guint" "index")
)
)
(define-method has_field (define-method has_field
(of-object "GstStructure") (of-object "GstStructure")
(c-name "gst_structure_has_field") (c-name "gst_structure_has_field")

View file

@ -40,32 +40,32 @@ pygst_caps_map_add (PyObject *structure, PyObject *caps)
g_hash_table_insert (structure_caps_map, structure, caps); g_hash_table_insert (structure_caps_map, structure, caps);
} }
/* static void */ static void
/* pygst_caps_map_remove_structure (PyObject *structure) */ pygst_caps_map_remove_structure (PyObject *structure)
/* { */ {
/* g_hash_table_remove (structure_caps_map, structure); */ g_hash_table_remove (structure_caps_map, structure);
/* } */ }
/* static gboolean */ static gboolean
/* pygst_caps_map_foreach (gpointer structure, gpointer caps, gpointer match) */ pygst_caps_map_foreach (gpointer structure, gpointer caps, gpointer match)
/* { */ {
/* PyGBoxed *boxed = structure; */ PyGBoxed *boxed = structure;
/* if (match != caps) */ if (match != caps)
/* return FALSE; */ return FALSE;
/* /\* we can't have free_on_dealloc stuff in here *\/ */ /* we can't have free_on_dealloc stuff in here */
/* g_assert (boxed->free_on_dealloc == FALSE); */ g_assert (boxed->free_on_dealloc == FALSE);
/* boxed->boxed = gst_structure_copy (boxed->boxed); */ boxed->boxed = gst_structure_copy (boxed->boxed);
/* boxed->free_on_dealloc = TRUE; */ boxed->free_on_dealloc = TRUE;
/* return TRUE; */ return TRUE;
/* } */ }
/* static void */ static void
/* pygst_caps_map_modified (PyObject *caps) */ pygst_caps_map_modified (PyObject *caps)
/* { */ {
/* g_hash_table_foreach_remove (structure_caps_map, pygst_caps_map_foreach, caps); */ g_hash_table_foreach_remove (structure_caps_map, pygst_caps_map_foreach, caps);
/* } */ }
%% %%
init init
@ -418,7 +418,7 @@ _wrap_gst_caps_tp_dealloc (PyObject *self)
PyGBoxed *boxed = (PyGBoxed *) self; PyGBoxed *boxed = (PyGBoxed *) self;
if (boxed->free_on_dealloc && boxed->boxed) { if (boxed->free_on_dealloc && boxed->boxed) {
pygst_caps_map_modified (self); pygst_caps_map_modified (self);
gst_caps_unref (boxed->boxed); gst_caps_unref (boxed->boxed);
} }

View file

@ -85,6 +85,21 @@ _wrap_gst_element_set_state(PyGObject *self, PyObject *args, PyObject *kwargs)
return PyInt_FromLong(ret); return PyInt_FromLong(ret);
} }
%% %%
override gst_element_get_state kwargs
static PyObject *
_wrap_gst_element_get_state(PyGObject *self, PyObject *args, PyObject *kwargs)
{
GstElementState state;
GstElementStateReturn ret;
ret = gst_element_get_state(GST_ELEMENT (self->obj), &state, NULL, NULL);
if (!ret) {
PyErr_SetString(PyExc_RuntimeError, "conversion could not be performed");
return NULL;
}
return pyg_flags_from_gtype(GST_TYPE_ELEMENT_STATE, state);
}
%%
/* override gst_element_query kwargs */ /* override gst_element_query kwargs */
/* static PyObject * */ /* static PyObject * */
/* _wrap_gst_element_query(PyGObject *self, PyObject *args, PyObject *kwargs) */ /* _wrap_gst_element_query(PyGObject *self, PyObject *args, PyObject *kwargs) */