Python中本机/C代码回调的组合

Python中本机/C代码回调的组合,python,scipy,ctypes,python-c-api,scientific-computing,Python,Scipy,Ctypes,Python C Api,Scientific Computing,我大量使用Python中的数值分析库,例如Scipy的优化和集成例程,其中许多例程都使用回调函数作为主要参数,该函数对某种目标函数进行求值。出于性能原因,我经常在本机代码中实现这些回调(通常使用Cython或Numba生成C代码,这些代码经过编译、链接,然后封装在Python对象中)。许多Scipy例程现在接受一个实例,这是一个包含指向C函数的指针及其签名信息的对象。如果例程本身是用C或Cython实现的,那么完全绕过Python解释器可以大大减少开销 我试图找出最好的方法是创建Python函数

我大量使用Python中的数值分析库,例如Scipy的优化和集成例程,其中许多例程都使用回调函数作为主要参数,该函数对某种目标函数进行求值。出于性能原因,我经常在本机代码中实现这些回调(通常使用Cython或Numba生成C代码,这些代码经过编译、链接,然后封装在Python对象中)。许多Scipy例程现在接受一个实例,这是一个包含指向C函数的指针及其签名信息的对象。如果例程本身是用C或Cython实现的,那么完全绕过Python解释器可以大大减少开销

我试图找出最好的方法是创建Python函数,这些函数接受这些类型的本机回调对象,以某种方式对它们进行转换,然后返回另一个本机回调。一个例子是一个函数,它接受一个预测给定
x
y
回调以及一个观察到的
y
值数组,并返回另一个回调,该回调计算预测与观察值相比的误差。然后可以将结果传递给
scipy.optimize.minimize()

常规Python函数的实现如下所示:

import numpy as np

def make_error_callback(f, y_obs):
    def g(x):
        y = f(x)
        return np.sum((y - y_obs) ** 2)

    return g

目标是,如果
f
是一个本机回调,可以在不调用Python解释器的情况下对其进行评估,那么
g
也应该是
make\u error\u callback
可能必须在Cython或类似的东西中实现(最糟糕的情况是使用Python的C API实现实际的C)。
f
g
的实际Python类型将是封装C函数指针的东西,如
scipy.LowLevelCallable

使用Numba也不会太复杂。示例: