P1: JYS
c11 JWBK378-Fletcher April 24, 2009 8:17 Printer: Yet to come
Hybrid Python/C++ Pricing Systems 161
11.2 EXERCISING nth imm of year FROM C++
We turn our attention now to ‘embedding’ a Python interpreter in a C++ program. We have
seen how to call C++ code from Python. Here we aim to do the reverse: call Python code
from C++. To do this we use a mix of Python C API routines together with helper types and
functions in the Boost.Python library:
#include <boost/detail/lightweight test.hpp>
#include <boost/python.hpp>
#include <boost/date
time/gregorian/gregorian.hpp>
int main()
{
namespace bd = boost::date
time;
namespace bg = boost::gregorian;
namespace python = boost::python;
typedef bd::year
based generator<bg::date> ybd t;
Py
Initialise();
try
{
//extract the ppf.date
time.nth imm of year class
//object
python::object main
module = python::import(" main ");
python::object global(main
module.attr(" dict "));
python::object result =
python::exec("from ppf.date
time import *\n", global, global);
python::object nth
imm of year class = global["nth imm of year"];
//use the class object to create instances of
//nth
imm of year
python::object first
imm = nth imm of year class(bg::Mar);
python::object second
imm = nth imm of year class(bg::Jun);
python::object third
imm = nth imm of year class(bg::Sep);
python::object fourth
imm = nth imm of year class(bg::Dec);
//get references to boost date
time year based generators
//from the newly created objects
ybd
t& first imm = python::extract<ybd t&>(first imm );
ybd
t& second imm = python::extract<ybd t&>(second imm );
ybd
t& third imm = python::extract<ybd t&>(third imm );
ybd
t& fourth imm = python::extract<ybd t&>(fourth imm );
//check imm dates for 2005
BOOST TEST(first imm.get date (2005) == bg::date(2005,
bg::Mar, 16));
BOOST
TEST(second imm.get date (2005) == bg::date(2005,
bg::Jun, 15));
BOOST
TEST(third imm.get date (2005) == bg::date(2005,
bg::Sep, 21));
BOOST
TEST(fourth imm.get date (2005) == bg::date(2005,
P1: JYS
c11 JWBK378-Fletcher April 24, 2009 8:17 Printer: Yet to come
162 Financial Modelling in Python
bg::Dec, 21));
}
catch(python::error
already set const&)
{
PyErr
Print();
}
catch(std::runtime
error const& e)
{
std::cerr << e.what() << std::endl;
}
catch(...)
{
std::cerr << "unexpected exception" << std::endl;
}
return boost::report
errors();
}
The significant steps in the above program are as follows: first, the Python interpreter is
initialised with the call to the Python C API function Py
Initialise(). Among other
things, this has the effect of creating the fundamental ’’
main ’’ module. The following
statements
python::object main module = python::import(" main ");
python::object global(main
module.attr(" dict "));
import the main module and obtain a reference to its namespace. With these the context
for executing Python code has been obtained and we execute
python::object result =
python::exec("from ppf.date
time import *\n", global, global);
to cause Python to import all types and functions in the ppf.date time module into the
global namespace. In particular, we are interested in the nth
imm of year class object
which we retrieve with
python::object nth imm of year class = global["nth imm of year"];
With the class object at our disposal, we use it to produce nth imm of year class instances
python::object first imm = nth imm of year class(bg::Mar);
python::object second
imm = nth imm of year class(bg::Jun);
python::object third
imm = nth imm of year class(bg::Sep);
python::object fourth
imm = nth imm of year class(bg::Dec);
This is the point at which things get interesting. Since nth imm of year IS A year
based generator<date> we can manipulate them through a year based
generator<date> reference or pointer
ybd t& first imm = python::extract<ybd t&>(first imm );
ybd
t& second imm = python::extract<ybd t&>(second imm );
ybd
t& third imm = python::extract<ybd t&>(third imm );
ybd
t& fourth imm = python::extract<ybd t&>(fourth imm );
P1: JYS
c11 JWBK378-Fletcher April 24, 2009 8:17 Printer: Yet to come
Hybrid Python/C++ Pricing Systems 163
Finally, invoking the virtual function get date on these references calls out to Python for
the implementation
BOOST TEST(first imm.get date (2005) == bg::date(2005,
bg::Mar, 16));
BOOST
TEST(second imm.get date (2005) == bg::date(2005,
bg::Jun, 15));
BOOST
TEST(third imm.get date (2005) == bg::date(2005,
bg::Sep, 21));
BOOST
TEST(fourth imm.get date (2005) == bg::date(2005,
bg::Dec, 21));
The net effect is that this shows how we can implement classes in Python and have them
behave as first-class C++ types in C++, a very powerful technique indeed!
P1: JYS
c11 JWBK378-Fletcher April 24, 2009 8:17 Printer: Yet to come
164

Get Financial Modelling in Python now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.