In a previous post we already covered calling a C function from one Boost.Python module in another module.
What if instead we want to call a Python function directly from C? We’ll stick with the same Bird / Quacker metaphor as in the previous post, but we’ll now implement our duck class in PyDuck.py:
""" PyDuck.py """ def quack(): print "Python Quack"
Now how can we call Python from C++? It turns out that Boost.Python defines operator() for the object class, so calling Python is relatively easy. But things become more difficult if we want to maintain a default implementation in C.
For example, one could imagine testing whether the Python object is set each time…
object quacker; void callQuack() { if (quacker) { quacker(); } else { default_quacker(); } }
But a cleaner approach is to instead use Boost.Function. This will allow all calls to use the same syntax as before, both when the quacker is set to a pure C function (i.e., default_quacker) or a callable Python object.
The final Bird.cpp file follows:
#include <boost/python.hpp> #include <boost/function.hpp> #include <iostream> using namespace boost::python; typedef void (quacker_t)(void); boost::function<quacker_t> quacker; void default_quacker() { std::cout << "No noise came out." << std::endl; } void setQuack(object obj) { quacker = obj; } void callQuack() { quacker(); } BOOST_PYTHON_MODULE(Bird) { quacker = &default_quacker; def("setQuack", &setQuack); def("callQuack", &callQuack); }
Testing it out:
>>> import Bird >>> import PyDuck >>> >>> Bird.callQuack() No noise came out. >>> >>> Bird.setQuack(PyDuck.quack) >>> Bird.callQuack() Python Quack
1 thought on “Calling Python from C++”