user56643 user56643 - 26 days ago 11
C++ Question

Using SWIG for functions with functions as input parameter

Consider the following minimal example: I have a C++ function 'myfun' that takes a number and another function as input, and returns the function evaluated at x:


double myfun(double x, double (*f)(double y))

{
return f(x);
}


I store this code in 'test.cpp'. The code in the corresponding header file 'test.hpp' is simply


double myfun(double x, double (*f)(double y));


Now, I try to access 'myfun' from Python using SWIG. The 'swig.i' file looks as follows:


%module test

%{

#include "test.hpp"

%}

double myfun(double x, double (*f)(double y));



Whenever I try to call this function in Python, e.g. with


from test import myfun

myfun(2, lambda y: y**2)


I receive the error:


in method 'myfun', argument 2 of type 'double (*)(double)'


So my question is simply: How to modifiy the 'swig.i' file such that I can pass any (suitable Python) function to 'myfun'? (The question is somewhat related to this post How to wrap a c++ function which takes in a function pointer in python using SWIG' but the difference is that here I do not specify the input function in C++, but instead I want to keep it as a free 'parameter').

Answer

Callbacks require extra treatment when writing bindings and this is not (yet) supported in SWIG and apparently there are no real workarounds.

The main point is that SWIG is about calling C from Python (and other languages), but not calling Python from C.

We are using SIP instead that is a much more sophisticated binding generator (that is however C++/Python specific). SIP supports callbacks and even inheriting Python classes from C++ classes.

The tool is pretty powerful and is the engine behind PyQt binding.