[Pyrex] Casting Python sequence to pointer and vice versa

Christian Heimes lists at cheimes.de
Fri Mar 2 12:05:46 UTC 2007


Hello!

I'm new to Pyrex. I had a lot of trouble casting a python sequence to a
pointer and the other way around. It required a lot of boiler plate code
and I hit a nasty gotcha.

ctypedef unsigned long ULong

cdef extern from "stdlib.h":
     ctypedef unsigned long size_t
     void *malloc(size_t size)
     void free(void* ptr)
     size_t sizeof(void *)

def xtea_encryptQuad(object block, key, UInt rounds):
     cdef *v
     cdef int size, vsize, i
     size = len(block)
     vsize = sizeof(ULong) * size
     v = <ULong *>malloc(vsize)
     for i from 0 <= i < size:
         v[i] = block[i]

     [more code]

     result = []
     for i from 0 <= i < size:
         result.append(v[i])
     free(v)

problem 1: The cdef extern from "stdlib.h" block isn't intuitive.
Although I know that the C functions are declared in stdlib.h I had to
google for the correct declarations.

problem 2 (the nasty gotcha): The usual malloc(sizeof(ULong)*size)
statement failed with a cryptic error message. It took me a while before
I found some pyrex code in another project with sizeof() and malloc().
It works when the statement is separated into two statements.

I wish Pyrex could get some nice PyArg_Parse() like methods to make our
lives either. Example code:

     cdef ULong *v
     cdef int size, rc
     block = (1, 2, 3)
     # cast Python block of unsigned longs (k) to unsigned long pointer
     # return size or -1 in the case of an error
     size = Py2Ptr(block, 'k', v)
     if size < 0:
         raise ValueError
     [...]
     result = []
     rc = Ptr2Py(v, size, 'k', result)
     if rc < 0:
         raise ValueError
     free(v)

Christian



More information about the Pyrex mailing list