returning a pointer from a cdef inline

950 views
Skip to first unread message

Eric Frederich

unread,
Sep 8, 2011, 2:03:55 PM9/8/11
to cython...@googlegroups.com
I can use PyCapsule_New and PyCapsule_GetPointer to move pointers
around between the C and Python realm.
I am having trouble now returning a pointer from an inline function.

Since Cython won't compile an inline function that returns a
non-python type I thought I'd have the inline function take a pointer
to the pointer as an argument.

from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer

ctypedef double* MYTYPE

cdef inline convert_MYTYPE_to_pycapsule(MYTYPE m):
return PyCapsule_New(m, NULL, NULL)

cdef inline convert_pycapsule_to_MYTYPE(c, MYTYPE *m):
cdef MYTYPE tmp
tmp = <MYTYPE>PyCapsule_GetPointer(c, NULL)
print 'tmp address is 0x%X' % <int>tmp
*m = tmp


The first function works fine, the second function doesn't compile.
Cython gives an error: Cannot assign type 'MYTYPE' to 'MYTYPE *'
If I remove the last line and run some code it prints the correct address.
So the tmp variable gets the correct pointer... how do I store that
pointer in m?

Robert Bradshaw

unread,
Sep 8, 2011, 3:28:29 PM9/8/11
to cython...@googlegroups.com

Cython can return pointers, you just have to declare the return type. E.g.

cdef inline int* func(args):
    return <int*>malloc(...)

On Sep 8, 2011 11:03 AM, "Eric Frederich" <eric.fr...@gmail.com> wrote:

Eric Frederich

unread,
Sep 8, 2011, 4:40:10 PM9/8/11
to cython...@googlegroups.com
Ahh... good to know.

But is it possible to set it when it comes in as a pointer argument though?

There are two lines commented out in the following code.
They both produce the same Cython error about not being able to
convert MYTYPE to MYTYPE*
That seems like a valid error for the first line, but not the second.

=== CODE ===

from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer

from libc.stdlib cimport malloc, free

ctypedef double* MYTYPE

cdef inline convert_MYTYPE_to_pycapsule(MYTYPE m):
return PyCapsule_New(m, NULL, NULL)

cdef inline convert_pycapsule_to_MYTYPE(c, MYTYPE* m):
cdef MYTYPE tmp
tmp = <MYTYPE>PyCapsule_GetPointer(c, NULL)
print 'tmp address is 0x%X' % <int>tmp

#m = tmp
#*m = tmp

def allocate_array(int n):
cdef MYTYPE m
m = <MYTYPE>malloc(n * sizeof(double))
return convert_MYTYPE_to_pycapsule(m)

def fill_array(c, n):
cdef MYTYPE m
m = <MYTYPE>PyCapsule_GetPointer(c, NULL)
for i in xrange(n):
m[i] = 2.0 ** i

def print_array(c, n):
cdef MYTYPE m
m = <MYTYPE>PyCapsule_GetPointer(c, NULL)
for i in xrange(n):
print i, 'is', m[i]

Robert Bradshaw

unread,
Sep 8, 2011, 6:00:59 PM9/8/11
to cython...@googlegroups.com
On Thu, Sep 8, 2011 at 1:40 PM, Eric Frederich <eric.fr...@gmail.com> wrote:
> Ahh... good to know.

It's also faster, as otherwise it's returning (and refcounting) None.

> But is it possible to set it when it comes in as a pointer argument though?

Yes.

> There are two lines commented out in the following code.
> They both produce the same Cython error about not being able to
> convert MYTYPE to MYTYPE*
> That seems like a valid error for the first line, but not the second.

Cython does not use the prefix * for dereferencing. (It's overloaded
to have too many other meanings in Python). Instead write "m[0] =
tmp."

- Robert

Reply all
Reply to author
Forward
0 new messages