[Pyrex] Questions re: malloc and instance variables...

Greg Ewing greg.ewing at canterbury.ac.nz
Tue Sep 26 04:25:59 UTC 2006


Adapted Cat wrote:
> The main problem comes when I get another object of the
> same class, e.g. for comparison or arithmetic operations.
> I can access self.my_struct but not other.my_struct,

You need type declarations. For example,

   cdef class myclass:
     cdef void *my_struct

     def foo(self, myclass other):
       do_something_with(other.mystruct)

Note that if you're implementing a binary operator
method such as __add__, you'll need

     def __add__(myclass x, myclass y):
       ...

i.e. don't assume that the first argument is "self"
(see the Special Methods of Extension Types pages for
a full explanation).

If you want to be able to add your type to things
of a different type, you'll need to do some type
testing, e.g.

     def __add__(x, y):
       cdef myclass my_x
       cdef myclass my_y
       if isinstance(x, myclass) and isinstance(y, myclass):
         my_x = x
         my_y = y
         do_something_with(my_x.my_struct, my_y.mystruct)
       else:
         # check for other type combinations and handle them

> I can't make Pyrex recognize a class function as
> returning other than a Python object,

Any function callable from Python (whether a method or
not) can only return a Python object. It may return an
instance of an extension type, but it can't be statically
declared as such, so you'll have to assign the result
to an appropriately-declared variable, as above, to
access its C attributes.

Alternatively, both top-level functions and (non-special)
extension type methods can be declared with "cdef", in
which case they can be declared as taking and returning
any type (including non-Python types). You can't call
such a function or method from Python, however.

> This may
> have something to do with the fact that I see malloc defined
> in the generated C code as taking an 'int' despite the note in
> the pyrex changelog (0.9.3) saying that typedefs are referred
> to as their original typedef name.

This only happens when the ctypedef is inside a
'cdef extern from' block. If you do it the way
you did in your posted code, with both the
ctypedef and the malloc declaration inside
'cdef extern from "stdlib.h"', you should find
that

(1) There will be *no* declaration of either
size_t or malloc in the code that Pyrex generates,
since they're assumed to come from the include
files, and

(2) if you do refer to size_t, e.g. to declare
a parameter or local variable, it will be left
as 'size_t' in the C code.

If you find that this is not happening, please
post an actual code example and I will investigate.

> In the spirit of "batteries included" couldn't Pyrex just parse
>   cdef int *c_array[len(input)]
> and do its own memory allocation and garbage collection in the
> generated C code?

In the simplistic sense of treating it as an
automatic variable and freeing it on exit from
the function, this might be doable. Don't
expect to see any sophisticated GC for types
other than Python objects, however. That would
be considerably outside Pyrex's scope.

> If not, is there a safe and portable way to
> do mallocs in Pyrex code?

If you put all the relevant declarations in
a 'cdef extern from' block as explained above,
it should be pretty safe.

-- 
Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury,	   | Carpe post meridiem!          	  |
Christchurch, New Zealand	   | (I'm not a morning person.)          |
greg.ewing at canterbury.ac.nz	   +--------------------------------------+



More information about the Pyrex mailing list