Reputation: 7317
A few SciPy functions (like scipy.ndimage.interpolation.geometric_transform
) can take pointers to C functions as arguments to avoid having to call a Python callable on each point of the input array.
In a nutshell :
my_function
somewhere in the C modulePyCObject
with the &my_function
pointer and (optionally) a void*
pointer to pass some global data aroundThe related API method is PyCObject_FromVoidPtrAndDesc
, and you can read Extending ndimage in C to see it in action.
I am very interested in using Cython to keep my code more manageable, but I'm not sure how exactly I should create such an object. Any, well,... pointers?
Upvotes: 6
Views: 1818
Reputation: 2820
Just do in Cython the same thing you would do in C, call PyCObject_FromVoidPtrAndDesc
directly. Here is an example from your link ported to Cython:
###### example.pyx ######
from libc.stdlib cimport malloc, free
from cpython.cobject cimport PyCObject_FromVoidPtrAndDesc
cdef int _shift_function(int *output_coordinates, double* input_coordinates,
int output_rank, int input_rank, double *shift_data):
cdef double shift = shift_data[0]
cdef int ii
for ii in range(input_rank):
input_coordinates[ii] = output_coordinates[ii] - shift
return 1
cdef void _shift_destructor(void* cobject, void *shift_data):
free(shift_data)
def shift_function(double shift):
"""This is the function callable from python."""
cdef double* shift_data = <double*>malloc(sizeof(shift))
shift_data[0] = shift
return PyCObject_FromVoidPtrAndDesc(&_shift_function,
shift_data,
&_shift_destructor)
Performance should be identical to pure C version.
Note that Cyhton requires operator &
to get function address. Also, Cython lacks pointer dereference operator *
, indexing equivalent is used instead (*ptr
-> ptr[0]
).
Upvotes: 1
Reputation: 572
I think that is a bad idea. Cython was created to avoid writing PyObjects also! Moreover, in this case, writing the code through Cython probably doesn't improve code maintenance... Anyway, you can import the PyObject with
from cpython.ref cimport PyObject
in your Cython code.
UPDATE
from cpython cimport *
is safer.
Cheers, Davide
Upvotes: 0