Hi all,
I'm quite new to cython, so apologies for stupid questions...
Here is my problem:
We have a C++ library (which optimizes robot trajectories if that matters), which gets std::function objects as callback. Let's say, they look like this:
class Optimizer {
public:
void optimize(std::function<double(double)> cost_fnc);
};
Giving it a cython function is easy (as function_pointers get casted to std::function and I can specify the desired signature in cython etc.).
cdef double my_cost_fnc(double x):
return x*3
# ...
o = Optimizer()
o.optimize(my_cost_fnc)
But now, we would like to give people the possibility to implement pure python functions without rebuilding the cython module and that's where my problem starts. Python functions do of course have not the right signature. The first thought was to make a local cdef and use that:
cdef void optimize_wrapper(func):
cdef double func_wrapper(double d):
return func(d)
o.optimize(func_wrapper)
But local cdef is not allowed. Ok, I thought, than I move it out and use functools.partial
cdef double func_wrapper(double d, func):
return func(d)
cdef void optimizer_wrapper(func):
wrapped = functools.partial(func_wrapper, func=func)
o.optimize(wrapped)
But then functools.partial returns of course a python object.
In the end I did the closure in C++, and wrapped everything with a void pointer and function pointers:
void optimize_wrapper(void* python_function, double (*cost) (void*, double)) {
optimize([](double x) { return cost(python_function, x); });
}
But then I have to touch the original library (or add another cpp file). Although it works, it feels a bit wrong. Is there any other way to achieve, what I want?
Cheers,
Johannes