One great feature of Boost.Python is the ability to write custom converters from Python types to C++ arguments. Most Boost.Python documentation, including the incredibly helpful post by misspent, show you how to write “rvalue” converters (e.g., pass-by-value or pass-by-const-reference).
However if you need to wrap a function which takes a
FILE* argument the previous approach will not prove fruitful. But Boost.Python is clearly capable of handling a similar situation, namely the implicit conversion from a Python string type to a
char* type. Since the conversion from the internal
char* is likely to be done with the PyString_AsString function, I went off in search of that code.
In two previous posts we showed how to call C functions from other modules and Python methods from within a Boost.Python module. Here we’ll show that the techniques are easily combined and demonstrate the atexit module which we’ll use to prevent Python interpreter crashes upon exit.
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:
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.
Python Capsules are useful for passing C pointers between different Python modules. In particular, one can encapsulate a C function pointer in one module and unpack and call it in another module.
To begin, suppose we have two Boost.Python modules:
- Bird, which has methods setQuack() and callQuack().
- CppDuck, which has a method getQuack().
Our goal will be to get a function pointer with CppDuck.getQuack(), set it in another module in Bird.setQuack(), and finally call it with Bird.callQuack().
I’ve been using Boost.Python to wrap a C++ library for use in Python for the past few months, and recently needed to have one compiled .so (or .pyd) file behave as a package instead of as a module. That is, I wanted the one file to behave as if it was actually a directory of Python files: