[Pyrex] cdef'd classes initialization
Daniele Varrazzo
daniele.varrazzo at gmail.com
Thu Aug 10 12:13:53 UTC 2006
Greg Ewing wrote:
> Lenard Lindstrom wrote:
>
>> The tp_alloc slot function returns a valid object except for user
>> defined fields, which are zeroed memory. PyType_GenericNew() makes
>> the call without doing anything else. So this should be what is
>> wanted. The problem with Pyrex are C methods. So what is needed is
>> some kind of extension type specific allocation operation that calls
>> tp_alloc and sets the vtable field, if any.
>
> There's also the problem of Python-valued C attributes --
> these are also initialised to None in the tp_new code
> that Pyrex generates. So that would need to be separated
> out somehow as well.
>
> And then there's also the issue of what happens when
> you derive from another type that needs its tp_new called
> in order to initialise it properly. You can't fully
> separate allocation from initialisation in that case,
> because the tp_alloc call happens at the bottom of the
> chain of tp_new calls. And you can't avoid allocating
> an argument tuple, because tp_new takes Python arguments.
Leonard put me on a promising way with his comment: i don't call
PyType_GenericNew(), but instead i call the function set by Pyrex in the
Type tp_new slot.
I refactored my classes splitting what required to create a viewer in
the __new__() method and what required to build an owner in __init__().
Then i created a factory function createViewer taking the Type of the
object to create and the pointer to the structure to wrap. Its
implementation boils down to:
cdef object createViewer(object t, void *s):
cdef PyTypeObject *pto
pto = <PyTypeObject *>t
cdef Asn1Base o
o = pto.tp_new(pto, (), {})
o.setStruct(s)
return o
the trick is to cast the type object to a PyTypeObject, then i can
access to its very __new__ method and create an object only initialized
for what i need.
Some external definition were required:
cdef extern from "Python.h":
cdef struct _typeobject
ctypedef object (*newfunc)(_typeobject *, object, object)
cdef struct _typeobject:
newfunc tp_new
ctypedef _typeobject PyTypeObject
What i obtained is:
1) from the interpreter only owners can be called: no more forbidden
options.
2) the factory provides a fully initialized viewer and is only
callable by Pyrex code
3) creating a viewer doesn't involve a Python call
...about all the issues i was concerned about.
All the test suite i prepared with the previous implementation worked
without glitch. I want to perform some deeper test to check for leaks
and such.
Does anybody foresee any problem in the approach i am testing? I
couldn't find documentation about the creation of a type from C: what it
seems to me is that it is enough to call tp_new to obtain a new object
(whose space is in turn allocated by tp_alloc) and tp_init to perform
__init__(). Am i missing something?
Thank you for the many hints,
Daniele
More information about the Pyrex
mailing list