The purpose of this section is to demonstrate how to invoke Python modules and C++ libraries and automatically display the results in the document. We use Matplotlib and the Sphinx extension plot directive .
Since this document is a proof of concept, we implement the functions
(1)
and
(2)
in both Python and C++.
This could be, for example, a library that reads data from many data sources and performs heavy computations.
Below we plot the functions (1), (2) on the interval [0,1].
We can easily display a different plot (for example, on [-1,1] by simply editing the code below and rebuilding the document.
from matplotlib import pyplot as plt
from LibPythonExample import func as func
N = 10
x = [i/N for i in range(0,N+1)]
#N=20
#x = [i/N for i in range(-N,N+1)]
y = [func.square(t) for t in x]
z = [func.cube(t) for t in x]
plt.plot(x, y, 'r')
plt.plot(x, y, '*r', label='square')
plt.plot(x, z, 'b')
plt.plot(x, z, 'ob', label='cube')
plt.xlabel('x')
plt.ylabel('values')
plt.title('Plots of $y = x^2$ and $z = x^3$')
plt.legend(loc='upper left')
(Source code, png, hires.png, pdf)
We implemented the same functions in C++. To show the flexibility of Python, we implemented one C++ function that returns both (1) and (2), as a Python dictionary.
Below, “func” (func.pyd) is the PYD file (similar to DLL) built from C++ files, not the Python module “func” we used above.
from matplotlib import pyplot as plt
import func as func
N = 10
x = [i/N for i in range(0,N+1)]
result = [func.calc(t) for t in x]
y = [r['square'] for r in result]
z = [r['cube'] for r in result]
plt.plot(x, y, 'r')
plt.plot(x, y, '*r', label='square')
plt.plot(x, z, 'b')
plt.plot(x, z, 'ob', label='cube')
plt.xlabel('x')
plt.ylabel('values')
plt.title('Plots of $y = x^2$ and $z = x^3$')
plt.legend(loc='upper left')
(Source code, png, hires.png, pdf)
We started from the example here:
https://en.wikibooks.org/wiki/Python_Programming/Extending_with_C.
Then we followed the official Python documentation:
https://docs.python.org/3.3/extending/extending.html.
The calculations are implemented in func.hpp, func.cpp, and the Python wrapper in funcWrapper.cpp.
One can build large libraries by following our example.
- We factored out the Python CPP wrapper. Thus the actual library can be built independently of Python.
- The Python wrapper turns Python data structures into C++ data structures. We showed a simple example, that takes a float and returns a two-key Python dictionary. This can quickly become complicated, in the case of rich I/O data structures, but it can be done. There are also off-the-shelf solutions: SWIG, SIP, and others.
We showed how we can invoke Python modules and C++ libraries directly from our document, to support the points we made in the introduction.
All computations are run at build time: enter “make html” at the command line in order to produce this document from source files (click on the link to the left to see the rst source file for this html page).