Functions¶
The simplest unit of code that can be exposed to Python from C++ is a function.
libpy supports automatically converting C++ functions into Python functions by adapting the parameter types and return type.
libpy uses py::autofunction() to convert a C++ function into a Python function definition 1.
The result of py::autofunction() can be attached to a Python module object and made available to Python.
A Simple C++ Function¶
Let’s start by writing a simple C++ function to expose to Python:
double fma(double a, double b, double c) {
return a * b + c;
}
fma is a standard C++ function with no knowledge of Python.
Adapting a Function¶
To adapt fma into a Python function, we need to use py::autofunction().
PyMethodDef fma_methoddef = py::autofunction<fma>("fma");
py::autofunction() is a template function which takes as a template argument the C++ function to adapt.
py::autofunction() also takes a string which is the name of the function as it will be exposed to Python.
The Python function name does not need to match the C++ name.
py::autofunction() takes an optional second argument: a string to use as the Python docstring.
For example, a docstring could be added to fma with:
PyMethodDef fma_methoddef = py::autofunction<fma>("fma", "Fused Multiply Add");
Warning
Currently the name and doc string parameters must outlive the resulting PyMethodDef.
In practice, this means it should be a static string, or string literal.
Adding the Function to a Module¶
To use an adapted function from Python, it must be attached to a module so that it may be imported by Python code.
To create a Python method, we can use LIBPY_AUTOMETHOD.
LIBPY_AUTOMETHOD is a macro which takes in the package name, the module name, and the set of functions to add.
Following the call to LIBPY_AUTOMETHOD, we must provide a function which is called when the module is first imported.
To just add functions, our body can be a simple return false to indicate that no errors occurred.
LIBPY_AUTOMODULE(libpy_tutorial, function, ({fma_methoddef}))
(py::borrowed_ref<>) {
return false;
}
Building and Importing the Module¶
To build a libpy extension, we can use setup.py and libpy’s LibpyExtension class.
In the setup.py's setup call, we can add a list of ext_modules to be built:
from libpy.build import LibpyExtension
setup(
# ...
ext_modules=[
LibpyExtension(
'libpy_tutorial.function',
['libpy_tutorial/function.cc'],
),
],
# ...
)
Now, the extension can be built with:
$ python setup.py build_ext --inplace
Finally, the function can be imported and used from python:
In [1]: import libpy # we need to ensure we import libpy before importing our extension
In [2]: from libpy_tutorial.function import fma
In [3]: fma(2.0, 3.0, 4.0)
Out[3]: 10.0
Footnotes
- 1
py::autofunction()creates aPyMethodDefinstance, which is not yet a Python object.