.. _square: Using Python and C++ libraries ================================ .. contents:: :depth: 3 :local: :backlinks: entry 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* . .. _Matplotlib: http://matplotlib.org/ Function definition ------------------------- Since this document is a proof of concept, we implement the functions .. math:: :label: square f(x) = x^2 and .. math:: :label: cube g(x) = x^3 in both Python and C++. This could be, for example, a library that reads data from many data sources and performs heavy computations. .. _squarePython: Using the Python module ------------------------- Results ^^^^^^^^^^ Below we plot the functions :eq:`square`, :eq:`cube` 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. .. plot:: :include-source: 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') Implementation ^^^^^^^^^^^^^^^^^^^^^^^^ .. automodule:: LibPythonExample.func :synopsis: square :members: :undoc-members: :show-inheritance: .. _squareCPP: Using the C++ library ------------------------ Results ^^^^^^^^^^ We implemented the same functions in C++. To show the flexibility of Python, we implemented one C++ function that returns both :eq:`square` and :eq:`cube`, 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 :ref:`above `. .. plot:: :include-source: 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') .. _squareCPPImpl: Implementation ^^^^^^^^^^^^^^^^^^^^^^^^ 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 :download:`func.hpp <../../LibCPPExample/func.hpp>`, :download:`func.cpp <../../LibCPPExample/func.cpp>`, and the Python wrapper in :download:`funcWrapper.cpp <../../LibCPPExample/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. .. _SWIG: http://www.swig.org/ .. _SIP: https://wiki.python.org/moin/SIP Conclusions ------------ 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).