Factor out the generation of the type structure away from cppclass into a separate class PyTypeObject, for better code reuse.

This commit is contained in:
Gustavo J. A. M. Carneiro committed 2008-08-08 18:54:21 +01:00
1 parent e716ffe780
commit ff031bfcda
2 files changed
+109 -68

No files matched your search

+6 -68
View File
@@ -15,6 +15,8 @@ from cppattribute import CppInstanceAttributeGetter, CppInstanceAttributeSetter,
CppStaticAttributeGetter, CppStaticAttributeSetter, \
PyGetSetDef, PyMetaclass
from pytypeobject import PyTypeObject
import settings
import utils
@@ -373,59 +375,6 @@ class CppClass(object):
A CppClass object takes care of generating the code for wrapping a C++ class
"""
TYPE_TMPL = (
'PyTypeObject %(typestruct)s = {\n'
' PyObject_HEAD_INIT(NULL)\n'
' 0, /* ob_size */\n'
' (char *) "%(tp_name)s", /* tp_name */\n'
' %(tp_basicsize)s, /* tp_basicsize */\n'
' 0, /* tp_itemsize */\n'
' /* methods */\n'
' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n'
' (printfunc)0, /* tp_print */\n'
' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n'
' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n'
' (cmpfunc)%(tp_compare)s, /* tp_compare */\n'
' (reprfunc)%(tp_repr)s, /* tp_repr */\n'
' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n'
' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n'
' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n'
' (hashfunc)%(tp_hash)s, /* tp_hash */\n'
' (ternaryfunc)%(tp_call)s, /* tp_call */\n'
' (reprfunc)%(tp_str)s, /* tp_str */\n'
' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n'
' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n'
' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n'
' %(tp_flags)s, /* tp_flags */\n'
' %(tp_doc)s, /* Documentation string */\n'
' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n'
' (inquiry)%(tp_clear)s, /* tp_clear */\n'
' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n'
' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n'
' (getiterfunc)%(tp_iter)s, /* tp_iter */\n'
' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n'
' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n'
' (struct PyMemberDef*)0, /* tp_members */\n'
' %(tp_getset)s, /* tp_getset */\n'
' NULL, /* tp_base */\n'
' NULL, /* tp_dict */\n'
' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n'
' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n'
' %(tp_dictoffset)s, /* tp_dictoffset */\n'
' (initproc)%(tp_init)s, /* tp_init */\n'
' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n'
' (newfunc)%(tp_new)s, /* tp_new */\n'
' (freefunc)%(tp_free)s, /* tp_free */\n'
' (inquiry)%(tp_is_gc)s, /* tp_is_gc */\n'
' NULL, /* tp_bases */\n'
' NULL, /* tp_mro */\n'
' NULL, /* tp_cache */\n'
' NULL, /* tp_subclasses */\n'
' NULL, /* tp_weaklist */\n'
' (destructor) NULL /* tp_del */\n'
'};\n'
)
def __init__(self, name, parent=None, incref_method=None, decref_method=None,
automatic_type_narrowing=None, allow_subclassing=None,
is_singleton=False, outer_class=None,
@@ -483,7 +432,8 @@ class CppClass(object):
self._dummy_methods = [] # methods that have parameter/retval binding problems
self.nonpublic_methods = []
self.constructors = [] # (name, wrapper) pairs
self.slots = dict()
self.pytype = PyTypeObject()
self.slots = self.pytype.slots
self.helper_class = None
self.instance_creation_function = None
## set to True when we become aware generating the helper
@@ -1456,19 +1406,7 @@ typedef struct {
"""generate the type structure"""
self.slots.setdefault("tp_basicsize",
"sizeof(%s)" % (self.pystruct,))
for slot in ["tp_getattr", "tp_setattr", "tp_compare", "tp_repr",
"tp_as_number", "tp_as_sequence", "tp_as_mapping",
"tp_hash", "tp_call", "tp_str", "tp_getattro", "tp_setattro",
"tp_as_buffer", "tp_traverse", "tp_clear", "tp_richcompare",
"tp_iter", "tp_iternext", "tp_descr_get",
"tp_descr_set", "tp_is_gc"]:
self.slots.setdefault(slot, "NULL")
self.slots.setdefault("tp_alloc", "PyType_GenericAlloc")
self.slots.setdefault("tp_new", "PyType_GenericNew")
#self.slots.setdefault("tp_free", "_PyObject_Del")
self.slots.setdefault("tp_free", "0")
self.slots.setdefault("tp_weaklistoffset", "0")
if self.allow_subclassing:
self.slots.setdefault("tp_flags", ("Py_TPFLAGS_DEFAULT|"
"Py_TPFLAGS_HAVE_GC|"
@@ -1489,8 +1427,8 @@ typedef struct {
dict_.setdefault("tp_name", '.'.join(mod_path))
else:
dict_.setdefault("tp_name", '%s.%s' % (self.outer_class.slots['tp_name'], self.name))
code_sink.writeln(self.TYPE_TMPL % dict_)
self.pytype.generate(code_sink)
def _generate_constructor(self, code_sink):
+103
View File
@@ -0,0 +1,103 @@
"""
The class PyTypeObject generates a PyTypeObject structure contents.
"""
class PyTypeObject(object):
TEMPLATE = (
'PyTypeObject %(typestruct)s = {\n'
' PyObject_HEAD_INIT(NULL)\n'
' 0, /* ob_size */\n'
' (char *) "%(tp_name)s", /* tp_name */\n'
' %(tp_basicsize)s, /* tp_basicsize */\n'
' 0, /* tp_itemsize */\n'
' /* methods */\n'
' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n'
' (printfunc)0, /* tp_print */\n'
' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n'
' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n'
' (cmpfunc)%(tp_compare)s, /* tp_compare */\n'
' (reprfunc)%(tp_repr)s, /* tp_repr */\n'
' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n'
' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n'
' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n'
' (hashfunc)%(tp_hash)s, /* tp_hash */\n'
' (ternaryfunc)%(tp_call)s, /* tp_call */\n'
' (reprfunc)%(tp_str)s, /* tp_str */\n'
' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n'
' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n'
' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n'
' %(tp_flags)s, /* tp_flags */\n'
' %(tp_doc)s, /* Documentation string */\n'
' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n'
' (inquiry)%(tp_clear)s, /* tp_clear */\n'
' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n'
' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n'
' (getiterfunc)%(tp_iter)s, /* tp_iter */\n'
' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n'
' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n'
' (struct PyMemberDef*)0, /* tp_members */\n'
' %(tp_getset)s, /* tp_getset */\n'
' NULL, /* tp_base */\n'
' NULL, /* tp_dict */\n'
' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n'
' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n'
' %(tp_dictoffset)s, /* tp_dictoffset */\n'
' (initproc)%(tp_init)s, /* tp_init */\n'
' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n'
' (newfunc)%(tp_new)s, /* tp_new */\n'
' (freefunc)%(tp_free)s, /* tp_free */\n'
' (inquiry)%(tp_is_gc)s, /* tp_is_gc */\n'
' NULL, /* tp_bases */\n'
' NULL, /* tp_mro */\n'
' NULL, /* tp_cache */\n'
' NULL, /* tp_subclasses */\n'
' NULL, /* tp_weaklist */\n'
' (destructor) NULL /* tp_del */\n'
'};\n'
)
def __init__(self):
self.slots = {}
def generate(self, code_sink):
"""
Generates the type structure. All slots are optional except
'tp_name', 'tp_basicsize', and the pseudo-slot 'typestruct'.
"""
slots = dict(self.slots)
slots.setdefault('tp_dealloc', 'NULL')
slots.setdefault('tp_getattr', 'NULL')
slots.setdefault('tp_setattr', 'NULL')
slots.setdefault('tp_compare', 'NULL')
slots.setdefault('tp_repr', 'NULL')
slots.setdefault('tp_as_number', 'NULL')
slots.setdefault('tp_as_sequence', 'NULL')
slots.setdefault('tp_as_mapping', 'NULL')
slots.setdefault('tp_hash', 'NULL')
slots.setdefault('tp_call', 'NULL')
slots.setdefault('tp_str', 'NULL')
slots.setdefault('tp_getattro', 'NULL')
slots.setdefault('tp_setattro', 'NULL')
slots.setdefault('tp_as_buffer', 'NULL')
slots.setdefault('tp_flags', 'Py_TPFLAGS_DEFAULT')
slots.setdefault('tp_doc', 'NULL')
slots.setdefault('tp_traverse', 'NULL')
slots.setdefault('tp_clear', 'NULL')
slots.setdefault('tp_richcompare', 'NULL')
slots.setdefault('tp_weaklistoffset', '0')
slots.setdefault('tp_iter', 'NULL')
slots.setdefault('tp_iternext', 'NULL')
slots.setdefault('tp_methods', 'NULL')
slots.setdefault('tp_getset', 'NULL')
slots.setdefault('tp_descr_get', 'NULL')
slots.setdefault('tp_descr_set', 'NULL')
slots.setdefault('tp_dictoffset', 'NULL')
slots.setdefault('tp_init', 'NULL')
slots.setdefault('tp_alloc', 'PyType_GenericAlloc')
slots.setdefault('tp_new', 'PyType_GenericNew')
slots.setdefault('tp_free', '0')
slots.setdefault('tp_is_gc', 'NULL')
code_sink.writeln(self.TEMPLATE % slots)