If you intend to pass only scalars as additional arguments for a SciPy quadrature, you can define your C structure using make_c_struct and utilize the LowLevelCallable function.
import numpy as np
import numba as nb
from numba import types
from scipy import integrate, LowLevelCallable
import ctypes
# Define the C-struct
args_dtype = types.Record.make_c_struct([
('x2', types.float64),
])
# function to integrate
def integrand(x1, x2):
return np.exp(-x1/x2) / x1**2
# function factory
def create_jit_integrand_function(integrand_function, args_dtype):
jitted_function = nb.njit(integrand_function)
# double func(double x, void *user_data)
@nb.cfunc(types.float64(types.float64, types.CPointer(args_dtype)))
def wrapped(x1, user_data_p):
user_data = nb.carray(user_data_p, 1)
x2 = user_data[0].x2
return jitted_function(x1, x2)
return wrapped
# wrapped function call
def do_integrate(func, args, a=0, b=1):
integrand_func = LowLevelCallable(func.ctypes, user_data=args.ctypes.data_as(ctypes.c_void_p))
# quadrature(func, a, b, args=(), tol=1.49e-8, rtol=1.49e-8, maxiter=50, vec_func=True, miniter=1)
return integrate.quad(integrand_func, a, b)
# How to use it:
x2 = 1.0
args = np.array((x2,), dtype=args_dtype)
func = create_jit_integrand_function(integrand, args_dtype)
print(do_integrate(func, args, a=1, b=np.inf))
# (0.14849550677592208, 3.8736750296130505e-10)
If you need to define arrays as arguments, there is an example by @max9111