Search code examples
scipypython-cffi

Using cffi function with scipy.integrate.nquad


I can't make scipy.integrate.nquad work with cffi function. I also couldn't find any examples of this online.

Let's say I have a simple c function in my test.py

ffibuilder.set_source("_test",     
    r""" #include <math.h>
        double test(int n, double* xx) {
            return xx[0]*xx[1];
        }
     """)

and I am trying to integrate it in a second file test_cffi.py like so

from _test import ffi, lib
from scipy.integrate import nquad

xx = ffi.new("double[]",2)
xx[0] = 1
xx[1] = 2
# This works.
print(lib.test(2,xx))
# This I can't make to work
print(nquad(lib.test3,[[0,1],[0,1]],args=(2,)))

What should I do on the last line above to make the integration work? Scipy documentation says the function signature has to be double f(int, double*).


Solution

  • The documentation talks about accepting a ctypes function, and it's probably special-cased inside nquad(). It says nothing about a cffi function, which means that there is no special support for that.

    You can try to take the address of the C-level function and wrap it manually inside a ctypes function, for nquad() to unwrap it again and call the C function directly:

    raw_addr = int(ffi.cast("intptr_t", ffi.addressof(lib, "test")))
    CF = ctypes.CFUNCTYPE(ctypes.c_double,
             ctypes.c_int, ctypes.POINTER(ctypes.c_double))
    wrapper_function = CF(raw_addr)