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?
Cython can return pointers, you just have to declare the return type. E.g.
cdef inline int* func(args):
return <int*>malloc(...)
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]
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