I'm trying to create a Cython function that depends on a Python function. The arguments of this Python function include a float and an array (I'm using Numpy arrays). I tried to follow this example Python/Cython/C and callbacks, calling a Python function from C using Cython but my code segfaults when is trying to access the array passed to the Python function. I have to make a callback function since I cannot pass a Python function to the C function directly. Below is a minimal example (my code is more complex than this example but the problem is the same)
example.py:
import numpy as np
from example_cython import my_function
def python_fun(x, x_arr):
"""
Add x to the elements of x_arr
"""
x_arr += x
return 0.0
A = np.arange(3.)
B = np.ones(3, dtype=np.float)
n = 3
x = 2.
# Call the C function using the Python one
my_function(A, B, n, x, python_fun)
example.c
#include<stdio.h>
// Add x to the elements of *a and then add the elements of *a to *b
void C_fun(double * a, double * b, int n, double x,
double (*f) (double, double *)
) {
printf("a: %f b: %f x: %f\n", a[0], b[0], x);
// Update array a
f(x, a);
for(int i=0; i<n; i++) b[i] += a[i];
}
example.h
void C_fun(double * a, double * b, int n, double x,
double (*f) (double, double *)
);
example_cython.pyx
# Function prototype for the C function
ctypedef double (*cfunction)(double x, double * y)
cdef object f
cdef extern from "example.h":
void C_fun(double * a, double * b, int n, double x,
double (*f) (double, double *)
)
cdef double cfunction_cb(double x, double [:] y):
global f
result = f(x, y)
return result
# This function calls the f function (a Python f) that updates *a and then sums
# the elements of *a into *b
def my_function(double [:] a, double [:] b, int n, double x, pythonf):
global f
f = pythonf
C_fun(&a[0], &b[0], n, x, <cfunction> cfunction_cb)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
extension_src = ["example_cython.pyx", "example.c"]
extensions = [
Extension("example_cython", extension_src)
]
setup(
ext_modules=cythonize(extensions),
)
Compiling the Cython module works, and I can access the C function and print the array contents, but when the function calls the array, it has the problem
a: 0.000000 b: 1.000000 x: 2.000000
[1] 791 segmentation fault (core dumped) python example.py