F.X.
F.X.

Reputation: 7317

Creating a PyCObject pointer in Cython

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 :

The 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

Answers (2)

Nikita Nemkin
Nikita Nemkin

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

Davide Albanese
Davide Albanese

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

Related Questions