article.html 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
  7. <title>Building Hybrid Systems with Boost.Python</title>
  8. <meta name="author" content="David Abrahams" />
  9. <meta name="organization" content="Boost Consulting" />
  10. <meta name="date" content="2003-05-14" />
  11. <meta name="author" content="Ralf W. Grosse-Kunstleve" />
  12. <meta name="copyright" content="Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved" />
  13. <link rel="stylesheet" href="rst.css" type="text/css" />
  14. </head>
  15. <body>
  16. <div class="document" id="building-hybrid-systems-with-boost-python">
  17. <h1 class="title">Building Hybrid Systems with Boost.Python</h1>
  18. <table class="docinfo" frame="void" rules="none">
  19. <col class="docinfo-name" />
  20. <col class="docinfo-content" />
  21. <tbody valign="top">
  22. <tr><th class="docinfo-name">Author:</th>
  23. <td>David Abrahams</td></tr>
  24. <tr><th class="docinfo-name">Contact:</th>
  25. <td><a class="first last reference external" href="mailto:dave&#64;boost-consulting.com">dave&#64;boost-consulting.com</a></td></tr>
  26. <tr><th class="docinfo-name">Organization:</th>
  27. <td><a class="first last reference external" href="http://www.boost-consulting.com">Boost Consulting</a></td></tr>
  28. <tr><th class="docinfo-name">Date:</th>
  29. <td>2003-05-14</td></tr>
  30. <tr><th class="docinfo-name">Author:</th>
  31. <td>Ralf W. Grosse-Kunstleve</td></tr>
  32. <tr><th class="docinfo-name">Copyright:</th>
  33. <td>Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved</td></tr>
  34. </tbody>
  35. </table>
  36. <div class="contents topic" id="table-of-contents">
  37. <p class="topic-title first">Table of Contents</p>
  38. <ul class="simple">
  39. <li><a class="reference internal" href="#abstract" id="id5">Abstract</a></li>
  40. <li><a class="reference internal" href="#introduction" id="id6">Introduction</a></li>
  41. <li><a class="reference internal" href="#boost-python-design-goals" id="id7">Boost.Python Design Goals</a></li>
  42. <li><a class="reference internal" href="#hello-boost-python-world" id="id8">Hello Boost.Python World</a></li>
  43. <li><a class="reference internal" href="#library-overview" id="id9">Library Overview</a><ul>
  44. <li><a class="reference internal" href="#exposing-classes" id="id10">Exposing Classes</a><ul>
  45. <li><a class="reference internal" href="#constructors" id="id11">Constructors</a></li>
  46. <li><a class="reference internal" href="#data-members-and-properties" id="id12">Data Members and Properties</a></li>
  47. <li><a class="reference internal" href="#operator-overloading" id="id13">Operator Overloading</a></li>
  48. <li><a class="reference internal" href="#inheritance" id="id14">Inheritance</a></li>
  49. <li><a class="reference internal" href="#virtual-functions" id="id15">Virtual Functions</a></li>
  50. <li><a class="reference internal" href="#deeper-reflection-on-the-horizon" id="id16">Deeper Reflection on the Horizon?</a></li>
  51. </ul>
  52. </li>
  53. <li><a class="reference internal" href="#serialization" id="id17">Serialization</a></li>
  54. <li><a class="reference internal" href="#object-interface" id="id18">Object interface</a></li>
  55. </ul>
  56. </li>
  57. <li><a class="reference internal" href="#thinking-hybrid" id="id19">Thinking hybrid</a></li>
  58. <li><a class="reference internal" href="#development-history" id="id20">Development history</a></li>
  59. <li><a class="reference internal" href="#conclusions" id="id21">Conclusions</a></li>
  60. <li><a class="reference internal" href="#citations" id="id22">Citations</a></li>
  61. <li><a class="reference internal" href="#footnotes" id="id23">Footnotes</a></li>
  62. </ul>
  63. </div>
  64. <div class="section" id="abstract">
  65. <h1><a class="toc-backref" href="#id5">Abstract</a></h1>
  66. <p>Boost.Python is an open source C++ library which provides a concise
  67. IDL-like interface for binding C++ classes and functions to
  68. Python. Leveraging the full power of C++ compile-time introspection
  69. and of recently developed metaprogramming techniques, this is achieved
  70. entirely in pure C++, without introducing a new syntax.
  71. Boost.Python's rich set of features and high-level interface make it
  72. possible to engineer packages from the ground up as hybrid systems,
  73. giving programmers easy and coherent access to both the efficient
  74. compile-time polymorphism of C++ and the extremely convenient run-time
  75. polymorphism of Python.</p>
  76. </div>
  77. <div class="section" id="introduction">
  78. <h1><a class="toc-backref" href="#id6">Introduction</a></h1>
  79. <p>Python and C++ are in many ways as different as two languages could
  80. be: while C++ is usually compiled to machine-code, Python is
  81. interpreted. Python's dynamic type system is often cited as the
  82. foundation of its flexibility, while in C++ static typing is the
  83. cornerstone of its efficiency. C++ has an intricate and difficult
  84. compile-time meta-language, while in Python, practically everything
  85. happens at runtime.</p>
  86. <p>Yet for many programmers, these very differences mean that Python and
  87. C++ complement one another perfectly. Performance bottlenecks in
  88. Python programs can be rewritten in C++ for maximal speed, and
  89. authors of powerful C++ libraries choose Python as a middleware
  90. language for its flexible system integration capabilities.
  91. Furthermore, the surface differences mask some strong similarities:</p>
  92. <ul class="simple">
  93. <li>'C'-family control structures (if, while, for...)</li>
  94. <li>Support for object-orientation, functional programming, and generic
  95. programming (these are both <em>multi-paradigm</em> programming languages.)</li>
  96. <li>Comprehensive operator overloading facilities, recognizing the
  97. importance of syntactic variability for readability and
  98. expressivity.</li>
  99. <li>High-level concepts such as collections and iterators.</li>
  100. <li>High-level encapsulation facilities (C++: namespaces, Python: modules)
  101. to support the design of re-usable libraries.</li>
  102. <li>Exception-handling for effective management of error conditions.</li>
  103. <li>C++ idioms in common use, such as handle/body classes and
  104. reference-counted smart pointers mirror Python reference semantics.</li>
  105. </ul>
  106. <p>Given Python's rich 'C' interoperability API, it should in principle
  107. be possible to expose C++ type and function interfaces to Python with
  108. an analogous interface to their C++ counterparts. However, the
  109. facilities provided by Python alone for integration with C++ are
  110. relatively meager. Compared to C++ and Python, 'C' has only very
  111. rudimentary abstraction facilities, and support for exception-handling
  112. is completely missing. 'C' extension module writers are required to
  113. manually manage Python reference counts, which is both annoyingly
  114. tedious and extremely error-prone. Traditional extension modules also
  115. tend to contain a great deal of boilerplate code repetition which
  116. makes them difficult to maintain, especially when wrapping an evolving
  117. API.</p>
  118. <p>These limitations have lead to the development of a variety of wrapping
  119. systems. <a class="reference external" href="http://www.swig.org/">SWIG</a> is probably the most popular package for the
  120. integration of C/C++ and Python. A more recent development is <a class="reference external" href="http://www.riverbankcomputing.co.uk/sip/index.php">SIP</a>,
  121. which was specifically designed for interfacing Python with the <a class="reference external" href="http://www.trolltech.com/">Qt</a>
  122. graphical user interface library. Both SWIG and SIP introduce their
  123. own specialized languages for customizing inter-language bindings.
  124. This has certain advantages, but having to deal with three different
  125. languages (Python, C/C++ and the interface language) also introduces
  126. practical and mental difficulties. The <a class="reference external" href="http://cxx.sourceforge.net/">CXX</a> package demonstrates an
  127. interesting alternative. It shows that at least some parts of
  128. Python's 'C' API can be wrapped and presented through a much more
  129. user-friendly C++ interface. However, unlike SWIG and SIP, CXX does
  130. not include support for wrapping C++ classes as new Python types.</p>
  131. <p>The features and goals of <a class="reference external" href="http://www.boost.org/libs/python/doc">Boost.Python</a> overlap significantly with
  132. many of these other systems. That said, Boost.Python attempts to
  133. maximize convenience and flexibility without introducing a separate
  134. wrapping language. Instead, it presents the user with a high-level
  135. C++ interface for wrapping C++ classes and functions, managing much of
  136. the complexity behind-the-scenes with static metaprogramming.
  137. Boost.Python also goes beyond the scope of earlier systems by
  138. providing:</p>
  139. <ul class="simple">
  140. <li>Support for C++ virtual functions that can be overridden in Python.</li>
  141. <li>Comprehensive lifetime management facilities for low-level C++
  142. pointers and references.</li>
  143. <li>Support for organizing extensions as Python packages,
  144. with a central registry for inter-language type conversions.</li>
  145. <li>A safe and convenient mechanism for tying into Python's powerful
  146. serialization engine (pickle).</li>
  147. <li>Coherence with the rules for handling C++ lvalues and rvalues that
  148. can only come from a deep understanding of both the Python and C++
  149. type systems.</li>
  150. </ul>
  151. <p>The key insight that sparked the development of Boost.Python is that
  152. much of the boilerplate code in traditional extension modules could be
  153. eliminated using C++ compile-time introspection. Each argument of a
  154. wrapped C++ function must be extracted from a Python object using a
  155. procedure that depends on the argument type. Similarly the function's
  156. return type determines how the return value will be converted from C++
  157. to Python. Of course argument and return types are part of each
  158. function's type, and this is exactly the source from which
  159. Boost.Python deduces most of the information required.</p>
  160. <p>This approach leads to <em>user guided wrapping</em>: as much information is
  161. extracted directly from the source code to be wrapped as is possible
  162. within the framework of pure C++, and some additional information is
  163. supplied explicitly by the user. Mostly the guidance is mechanical
  164. and little real intervention is required. Because the interface
  165. specification is written in the same full-featured language as the
  166. code being exposed, the user has unprecedented power available when
  167. she does need to take control.</p>
  168. </div>
  169. <div class="section" id="boost-python-design-goals">
  170. <h1><a class="toc-backref" href="#id7">Boost.Python Design Goals</a></h1>
  171. <p>The primary goal of Boost.Python is to allow users to expose C++
  172. classes and functions to Python using nothing more than a C++
  173. compiler. In broad strokes, the user experience should be one of
  174. directly manipulating C++ objects from Python.</p>
  175. <p>However, it's also important not to translate all interfaces <em>too</em>
  176. literally: the idioms of each language must be respected. For
  177. example, though C++ and Python both have an iterator concept, they are
  178. expressed very differently. Boost.Python has to be able to bridge the
  179. interface gap.</p>
  180. <p>It must be possible to insulate Python users from crashes resulting
  181. from trivial misuses of C++ interfaces, such as accessing
  182. already-deleted objects. By the same token the library should
  183. insulate C++ users from low-level Python 'C' API, replacing
  184. error-prone 'C' interfaces like manual reference-count management and
  185. raw <tt class="docutils literal">PyObject</tt> pointers with more-robust alternatives.</p>
  186. <p>Support for component-based development is crucial, so that C++ types
  187. exposed in one extension module can be passed to functions exposed in
  188. another without loss of crucial information like C++ inheritance
  189. relationships.</p>
  190. <p>Finally, all wrapping must be <em>non-intrusive</em>, without modifying or
  191. even seeing the original C++ source code. Existing C++ libraries have
  192. to be wrappable by third parties who only have access to header files
  193. and binaries.</p>
  194. </div>
  195. <div class="section" id="hello-boost-python-world">
  196. <h1><a class="toc-backref" href="#id8">Hello Boost.Python World</a></h1>
  197. <p>And now for a preview of Boost.Python, and how it improves on the raw
  198. facilities offered by Python. Here's a function we might want to
  199. expose:</p>
  200. <pre class="literal-block">
  201. char const* greet(unsigned x)
  202. {
  203. static char const* const msgs[] = { &quot;hello&quot;, &quot;Boost.Python&quot;, &quot;world!&quot; };
  204. if (x &gt; 2)
  205. throw std::range_error(&quot;greet: index out of range&quot;);
  206. return msgs[x];
  207. }
  208. </pre>
  209. <p>To wrap this function in standard C++ using the Python 'C' API, we'd
  210. need something like this:</p>
  211. <pre class="literal-block">
  212. extern &quot;C&quot; // all Python interactions use 'C' linkage and calling convention
  213. {
  214. // Wrapper to handle argument/result conversion and checking
  215. PyObject* greet_wrap(PyObject* args, PyObject * keywords)
  216. {
  217. int x;
  218. if (PyArg_ParseTuple(args, &quot;i&quot;, &amp;x)) // extract/check arguments
  219. {
  220. char const* result = greet(x); // invoke wrapped function
  221. return PyString_FromString(result); // convert result to Python
  222. }
  223. return 0; // error occurred
  224. }
  225. // Table of wrapped functions to be exposed by the module
  226. static PyMethodDef methods[] = {
  227. { &quot;greet&quot;, greet_wrap, METH_VARARGS, &quot;return one of 3 parts of a greeting&quot; }
  228. , { NULL, NULL, 0, NULL } // sentinel
  229. };
  230. // module initialization function
  231. DL_EXPORT init_hello()
  232. {
  233. (void) Py_InitModule(&quot;hello&quot;, methods); // add the methods to the module
  234. }
  235. }
  236. </pre>
  237. <p>Now here's the wrapping code we'd use to expose it with Boost.Python:</p>
  238. <pre class="literal-block">
  239. #include &lt;boost/python.hpp&gt;
  240. using namespace boost::python;
  241. BOOST_PYTHON_MODULE(hello)
  242. {
  243. def(&quot;greet&quot;, greet, &quot;return one of 3 parts of a greeting&quot;);
  244. }
  245. </pre>
  246. <p>and here it is in action:</p>
  247. <pre class="literal-block">
  248. &gt;&gt;&gt; import hello
  249. &gt;&gt;&gt; for x in range(3):
  250. ... print hello.greet(x)
  251. ...
  252. hello
  253. Boost.Python
  254. world!
  255. </pre>
  256. <p>Aside from the fact that the 'C' API version is much more verbose,
  257. it's worth noting a few things that it doesn't handle correctly:</p>
  258. <ul class="simple">
  259. <li>The original function accepts an unsigned integer, and the Python
  260. 'C' API only gives us a way of extracting signed integers. The
  261. Boost.Python version will raise a Python exception if we try to pass
  262. a negative number to <tt class="docutils literal">hello.greet</tt>, but the other one will proceed
  263. to do whatever the C++ implementation does when converting an
  264. negative integer to unsigned (usually wrapping to some very large
  265. number), and pass the incorrect translation on to the wrapped
  266. function.</li>
  267. <li>That brings us to the second problem: if the C++ <tt class="docutils literal">greet()</tt>
  268. function is called with a number greater than 2, it will throw an
  269. exception. Typically, if a C++ exception propagates across the
  270. boundary with code generated by a 'C' compiler, it will cause a
  271. crash. As you can see in the first version, there's no C++
  272. scaffolding there to prevent this from happening. Functions wrapped
  273. by Boost.Python automatically include an exception-handling layer
  274. which protects Python users by translating unhandled C++ exceptions
  275. into a corresponding Python exception.</li>
  276. <li>A slightly more-subtle limitation is that the argument conversion
  277. used in the Python 'C' API case can only get that integer <tt class="docutils literal">x</tt> in
  278. <em>one way</em>. PyArg_ParseTuple can't convert Python <tt class="docutils literal">long</tt> objects
  279. (arbitrary-precision integers) which happen to fit in an <tt class="docutils literal">unsigned
  280. int</tt> but not in a <tt class="docutils literal">signed long</tt>, nor will it ever handle a
  281. wrapped C++ class with a user-defined implicit <tt class="docutils literal">operator unsigned
  282. int()</tt> conversion. Boost.Python's dynamic type conversion
  283. registry allows users to add arbitrary conversion methods.</li>
  284. </ul>
  285. </div>
  286. <div class="section" id="library-overview">
  287. <h1><a class="toc-backref" href="#id9">Library Overview</a></h1>
  288. <p>This section outlines some of the library's major features. Except as
  289. neccessary to avoid confusion, details of library implementation are
  290. omitted.</p>
  291. <div class="section" id="exposing-classes">
  292. <h2><a class="toc-backref" href="#id10">Exposing Classes</a></h2>
  293. <p>C++ classes and structs are exposed with a similarly-terse interface.
  294. Given:</p>
  295. <pre class="literal-block">
  296. struct World
  297. {
  298. void set(std::string msg) { this-&gt;msg = msg; }
  299. std::string greet() { return msg; }
  300. std::string msg;
  301. };
  302. </pre>
  303. <p>The following code will expose it in our extension module:</p>
  304. <pre class="literal-block">
  305. #include &lt;boost/python.hpp&gt;
  306. BOOST_PYTHON_MODULE(hello)
  307. {
  308. class_&lt;World&gt;(&quot;World&quot;)
  309. .def(&quot;greet&quot;, &amp;World::greet)
  310. .def(&quot;set&quot;, &amp;World::set)
  311. ;
  312. }
  313. </pre>
  314. <p>Although this code has a certain pythonic familiarity, people
  315. sometimes find the syntax bit confusing because it doesn't look like
  316. most of the C++ code they're used to. All the same, this is just
  317. standard C++. Because of their flexible syntax and operator
  318. overloading, C++ and Python are great for defining domain-specific
  319. (sub)languages
  320. (DSLs), and that's what we've done in Boost.Python. To break it down:</p>
  321. <pre class="literal-block">
  322. class_&lt;World&gt;(&quot;World&quot;)
  323. </pre>
  324. <p>constructs an unnamed object of type <tt class="docutils literal">class_&lt;World&gt;</tt> and passes
  325. <tt class="docutils literal">&quot;World&quot;</tt> to its constructor. This creates a new-style Python class
  326. called <tt class="docutils literal">World</tt> in the extension module, and associates it with the
  327. C++ type <tt class="docutils literal">World</tt> in the Boost.Python type conversion registry. We
  328. might have also written:</p>
  329. <pre class="literal-block">
  330. class_&lt;World&gt; w(&quot;World&quot;);
  331. </pre>
  332. <p>but that would've been more verbose, since we'd have to name <tt class="docutils literal">w</tt>
  333. again to invoke its <tt class="docutils literal">def()</tt> member function:</p>
  334. <pre class="literal-block">
  335. w.def(&quot;greet&quot;, &amp;World::greet)
  336. </pre>
  337. <p>There's nothing special about the location of the dot for member
  338. access in the original example: C++ allows any amount of whitespace on
  339. either side of a token, and placing the dot at the beginning of each
  340. line allows us to chain as many successive calls to member functions
  341. as we like with a uniform syntax. The other key fact that allows
  342. chaining is that <tt class="docutils literal">class_&lt;&gt;</tt> member functions all return a reference
  343. to <tt class="docutils literal">*this</tt>.</p>
  344. <p>So the example is equivalent to:</p>
  345. <pre class="literal-block">
  346. class_&lt;World&gt; w(&quot;World&quot;);
  347. w.def(&quot;greet&quot;, &amp;World::greet);
  348. w.def(&quot;set&quot;, &amp;World::set);
  349. </pre>
  350. <p>It's occasionally useful to be able to break down the components of a
  351. Boost.Python class wrapper in this way, but the rest of this article
  352. will stick to the terse syntax.</p>
  353. <p>For completeness, here's the wrapped class in use:</p>
  354. <pre class="literal-block">
  355. &gt;&gt;&gt; import hello
  356. &gt;&gt;&gt; planet = hello.World()
  357. &gt;&gt;&gt; planet.set('howdy')
  358. &gt;&gt;&gt; planet.greet()
  359. 'howdy'
  360. </pre>
  361. <div class="section" id="constructors">
  362. <h3><a class="toc-backref" href="#id11">Constructors</a></h3>
  363. <p>Since our <tt class="docutils literal">World</tt> class is just a plain <tt class="docutils literal">struct</tt>, it has an
  364. implicit no-argument (nullary) constructor. Boost.Python exposes the
  365. nullary constructor by default, which is why we were able to write:</p>
  366. <pre class="literal-block">
  367. &gt;&gt;&gt; planet = hello.World()
  368. </pre>
  369. <p>However, well-designed classes in any language may require constructor
  370. arguments in order to establish their invariants. Unlike Python,
  371. where <tt class="docutils literal">__init__</tt> is just a specially-named method, In C++
  372. constructors cannot be handled like ordinary member functions. In
  373. particular, we can't take their address: <tt class="docutils literal"><span class="pre">&amp;World::World</span></tt> is an
  374. error. The library provides a different interface for specifying
  375. constructors. Given:</p>
  376. <pre class="literal-block">
  377. struct World
  378. {
  379. World(std::string msg); // added constructor
  380. ...
  381. </pre>
  382. <p>we can modify our wrapping code as follows:</p>
  383. <pre class="literal-block">
  384. class_&lt;World&gt;(&quot;World&quot;, init&lt;std::string&gt;())
  385. ...
  386. </pre>
  387. <p>of course, a C++ class may have additional constructors, and we can
  388. expose those as well by passing more instances of <tt class="docutils literal"><span class="pre">init&lt;...&gt;</span></tt> to
  389. <tt class="docutils literal">def()</tt>:</p>
  390. <pre class="literal-block">
  391. class_&lt;World&gt;(&quot;World&quot;, init&lt;std::string&gt;())
  392. .def(init&lt;double, double&gt;())
  393. ...
  394. </pre>
  395. <p>Boost.Python allows wrapped functions, member functions, and
  396. constructors to be overloaded to mirror C++ overloading.</p>
  397. </div>
  398. <div class="section" id="data-members-and-properties">
  399. <h3><a class="toc-backref" href="#id12">Data Members and Properties</a></h3>
  400. <p>Any publicly-accessible data members in a C++ class can be easily
  401. exposed as either <tt class="docutils literal">readonly</tt> or <tt class="docutils literal">readwrite</tt> attributes:</p>
  402. <pre class="literal-block">
  403. class_&lt;World&gt;(&quot;World&quot;, init&lt;std::string&gt;())
  404. .def_readonly(&quot;msg&quot;, &amp;World::msg)
  405. ...
  406. </pre>
  407. <p>and can be used directly in Python:</p>
  408. <pre class="literal-block">
  409. &gt;&gt;&gt; planet = hello.World('howdy')
  410. &gt;&gt;&gt; planet.msg
  411. 'howdy'
  412. </pre>
  413. <p>This does <em>not</em> result in adding attributes to the <tt class="docutils literal">World</tt> instance
  414. <tt class="docutils literal">__dict__</tt>, which can result in substantial memory savings when
  415. wrapping large data structures. In fact, no instance <tt class="docutils literal">__dict__</tt>
  416. will be created at all unless attributes are explicitly added from
  417. Python. Boost.Python owes this capability to the new Python 2.2 type
  418. system, in particular the descriptor interface and <tt class="docutils literal">property</tt> type.</p>
  419. <p>In C++, publicly-accessible data members are considered a sign of poor
  420. design because they break encapsulation, and style guides usually
  421. dictate the use of &quot;getter&quot; and &quot;setter&quot; functions instead. In
  422. Python, however, <tt class="docutils literal">__getattr__</tt>, <tt class="docutils literal">__setattr__</tt>, and since 2.2,
  423. <tt class="docutils literal">property</tt> mean that attribute access is just one more
  424. well-encapsulated syntactic tool at the programmer's disposal.
  425. Boost.Python bridges this idiomatic gap by making Python <tt class="docutils literal">property</tt>
  426. creation directly available to users. If <tt class="docutils literal">msg</tt> were private, we
  427. could still expose it as attribute in Python as follows:</p>
  428. <pre class="literal-block">
  429. class_&lt;World&gt;(&quot;World&quot;, init&lt;std::string&gt;())
  430. .add_property(&quot;msg&quot;, &amp;World::greet, &amp;World::set)
  431. ...
  432. </pre>
  433. <p>The example above mirrors the familiar usage of properties in Python
  434. 2.2+:</p>
  435. <pre class="literal-block">
  436. &gt;&gt;&gt; class World(object):
  437. ... __init__(self, msg):
  438. ... self.__msg = msg
  439. ... def greet(self):
  440. ... return self.__msg
  441. ... def set(self, msg):
  442. ... self.__msg = msg
  443. ... msg = property(greet, set)
  444. </pre>
  445. </div>
  446. <div class="section" id="operator-overloading">
  447. <h3><a class="toc-backref" href="#id13">Operator Overloading</a></h3>
  448. <p>The ability to write arithmetic operators for user-defined types has
  449. been a major factor in the success of both languages for numerical
  450. computation, and the success of packages like <a class="reference external" href="http://www.pfdubois.com/numpy/">NumPy</a> attests to the
  451. power of exposing operators in extension modules. Boost.Python
  452. provides a concise mechanism for wrapping operator overloads. The
  453. example below shows a fragment from a wrapper for the Boost rational
  454. number library:</p>
  455. <pre class="literal-block">
  456. class_&lt;rational&lt;int&gt; &gt;(&quot;rational_int&quot;)
  457. .def(init&lt;int, int&gt;()) // constructor, e.g. rational_int(3,4)
  458. .def(&quot;numerator&quot;, &amp;rational&lt;int&gt;::numerator)
  459. .def(&quot;denominator&quot;, &amp;rational&lt;int&gt;::denominator)
  460. .def(-self) // __neg__ (unary minus)
  461. .def(self + self) // __add__ (homogeneous)
  462. .def(self * self) // __mul__
  463. .def(self + int()) // __add__ (heterogenous)
  464. .def(int() + self) // __radd__
  465. ...
  466. </pre>
  467. <p>The magic is performed using a simplified application of &quot;expression
  468. templates&quot; <a class="citation-reference" href="#veld1995" id="id1">[VELD1995]</a>, a technique originally developed for
  469. optimization of high-performance matrix algebra expressions. The
  470. essence is that instead of performing the computation immediately,
  471. operators are overloaded to construct a type <em>representing</em> the
  472. computation. In matrix algebra, dramatic optimizations are often
  473. available when the structure of an entire expression can be taken into
  474. account, rather than evaluating each operation &quot;greedily&quot;.
  475. Boost.Python uses the same technique to build an appropriate Python
  476. method object based on expressions involving <tt class="docutils literal">self</tt>.</p>
  477. </div>
  478. <div class="section" id="inheritance">
  479. <h3><a class="toc-backref" href="#id14">Inheritance</a></h3>
  480. <p>C++ inheritance relationships can be represented to Boost.Python by adding
  481. an optional <tt class="docutils literal"><span class="pre">bases&lt;...&gt;</span></tt> argument to the <tt class="docutils literal"><span class="pre">class_&lt;...&gt;</span></tt> template
  482. parameter list as follows:</p>
  483. <pre class="literal-block">
  484. class_&lt;Derived, bases&lt;Base1,Base2&gt; &gt;(&quot;Derived&quot;)
  485. ...
  486. </pre>
  487. <p>This has two effects:</p>
  488. <ol class="arabic simple">
  489. <li>When the <tt class="docutils literal"><span class="pre">class_&lt;...&gt;</span></tt> is created, Python type objects
  490. corresponding to <tt class="docutils literal">Base1</tt> and <tt class="docutils literal">Base2</tt> are looked up in
  491. Boost.Python's registry, and are used as bases for the new Python
  492. <tt class="docutils literal">Derived</tt> type object, so methods exposed for the Python <tt class="docutils literal">Base1</tt>
  493. and <tt class="docutils literal">Base2</tt> types are automatically members of the <tt class="docutils literal">Derived</tt>
  494. type. Because the registry is global, this works correctly even if
  495. <tt class="docutils literal">Derived</tt> is exposed in a different module from either of its
  496. bases.</li>
  497. <li>C++ conversions from <tt class="docutils literal">Derived</tt> to its bases are added to the
  498. Boost.Python registry. Thus wrapped C++ methods expecting (a
  499. pointer or reference to) an object of either base type can be
  500. called with an object wrapping a <tt class="docutils literal">Derived</tt> instance. Wrapped
  501. member functions of class <tt class="docutils literal">T</tt> are treated as though they have an
  502. implicit first argument of <tt class="docutils literal">T&amp;</tt>, so these conversions are
  503. neccessary to allow the base class methods to be called for derived
  504. objects.</li>
  505. </ol>
  506. <p>Of course it's possible to derive new Python classes from wrapped C++
  507. class instances. Because Boost.Python uses the new-style class
  508. system, that works very much as for the Python built-in types. There
  509. is one significant detail in which it differs: the built-in types
  510. generally establish their invariants in their <tt class="docutils literal">__new__</tt> function, so
  511. that derived classes do not need to call <tt class="docutils literal">__init__</tt> on the base
  512. class before invoking its methods :</p>
  513. <pre class="literal-block">
  514. &gt;&gt;&gt; class L(list):
  515. ... def __init__(self):
  516. ... pass
  517. ...
  518. &gt;&gt;&gt; L().reverse()
  519. &gt;&gt;&gt;
  520. </pre>
  521. <p>Because C++ object construction is a one-step operation, C++ instance
  522. data cannot be constructed until the arguments are available, in the
  523. <tt class="docutils literal">__init__</tt> function:</p>
  524. <pre class="literal-block">
  525. &gt;&gt;&gt; class D(SomeBoostPythonClass):
  526. ... def __init__(self):
  527. ... pass
  528. ...
  529. &gt;&gt;&gt; D().some_boost_python_method()
  530. Traceback (most recent call last):
  531. File &quot;&lt;stdin&gt;&quot;, line 1, in ?
  532. TypeError: bad argument type for built-in operation
  533. </pre>
  534. <p>This happened because Boost.Python couldn't find instance data of type
  535. <tt class="docutils literal">SomeBoostPythonClass</tt> within the <tt class="docutils literal">D</tt> instance; <tt class="docutils literal">D</tt>'s <tt class="docutils literal">__init__</tt>
  536. function masked construction of the base class. It could be corrected
  537. by either removing <tt class="docutils literal">D</tt>'s <tt class="docutils literal">__init__</tt> function or having it call
  538. <tt class="docutils literal"><span class="pre">SomeBoostPythonClass.__init__(...)</span></tt> explicitly.</p>
  539. </div>
  540. <div class="section" id="virtual-functions">
  541. <h3><a class="toc-backref" href="#id15">Virtual Functions</a></h3>
  542. <p>Deriving new types in Python from extension classes is not very
  543. interesting unless they can be used polymorphically from C++. In
  544. other words, Python method implementations should appear to override
  545. the implementation of C++ virtual functions when called <em>through base
  546. class pointers/references from C++</em>. Since the only way to alter the
  547. behavior of a virtual function is to override it in a derived class,
  548. the user must build a special derived class to dispatch a polymorphic
  549. class' virtual functions:</p>
  550. <pre class="literal-block">
  551. //
  552. // interface to wrap:
  553. //
  554. class Base
  555. {
  556. public:
  557. virtual int f(std::string x) { return 42; }
  558. virtual ~Base();
  559. };
  560. int calls_f(Base const&amp; b, std::string x) { return b.f(x); }
  561. //
  562. // Wrapping Code
  563. //
  564. // Dispatcher class
  565. struct BaseWrap : Base
  566. {
  567. // Store a pointer to the Python object
  568. BaseWrap(PyObject* self_) : self(self_) {}
  569. PyObject* self;
  570. // Default implementation, for when f is not overridden
  571. int f_default(std::string x) { return this-&gt;Base::f(x); }
  572. // Dispatch implementation
  573. int f(std::string x) { return call_method&lt;int&gt;(self, &quot;f&quot;, x); }
  574. };
  575. ...
  576. def(&quot;calls_f&quot;, calls_f);
  577. class_&lt;Base, BaseWrap&gt;(&quot;Base&quot;)
  578. .def(&quot;f&quot;, &amp;Base::f, &amp;BaseWrap::f_default)
  579. ;
  580. </pre>
  581. <p>Now here's some Python code which demonstrates:</p>
  582. <pre class="literal-block">
  583. &gt;&gt;&gt; class Derived(Base):
  584. ... def f(self, s):
  585. ... return len(s)
  586. ...
  587. &gt;&gt;&gt; calls_f(Base(), 'foo')
  588. 42
  589. &gt;&gt;&gt; calls_f(Derived(), 'forty-two')
  590. 9
  591. </pre>
  592. <p>Things to notice about the dispatcher class:</p>
  593. <ul class="simple">
  594. <li>The key element which allows overriding in Python is the
  595. <tt class="docutils literal">call_method</tt> invocation, which uses the same global type
  596. conversion registry as the C++ function wrapping does to convert its
  597. arguments from C++ to Python and its return type from Python to C++.</li>
  598. <li>Any constructor signatures you wish to wrap must be replicated with
  599. an initial <tt class="docutils literal">PyObject*</tt> argument</li>
  600. <li>The dispatcher must store this argument so that it can be used to
  601. invoke <tt class="docutils literal">call_method</tt></li>
  602. <li>The <tt class="docutils literal">f_default</tt> member function is needed when the function being
  603. exposed is not pure virtual; there's no other way <tt class="docutils literal"><span class="pre">Base::f</span></tt> can be
  604. called on an object of type <tt class="docutils literal">BaseWrap</tt>, since it overrides <tt class="docutils literal">f</tt>.</li>
  605. </ul>
  606. </div>
  607. <div class="section" id="deeper-reflection-on-the-horizon">
  608. <h3><a class="toc-backref" href="#id16">Deeper Reflection on the Horizon?</a></h3>
  609. <p>Admittedly, this formula is tedious to repeat, especially on a project
  610. with many polymorphic classes. That it is neccessary reflects some
  611. limitations in C++'s compile-time introspection capabilities: there's
  612. no way to enumerate the members of a class and find out which are
  613. virtual functions. At least one very promising project has been
  614. started to write a front-end which can generate these dispatchers (and
  615. other wrapping code) automatically from C++ headers.</p>
  616. <p><a class="reference external" href="http://www.boost.org/libs/python/pyste">Pyste</a> is being developed by Bruno da Silva de Oliveira. It builds on
  617. <a class="reference external" href="http://www.gccxml.org/HTML/Index.html">GCC_XML</a>, which generates an XML version of GCC's internal program
  618. representation. Since GCC is a highly-conformant C++ compiler, this
  619. ensures correct handling of the most-sophisticated template code and
  620. full access to the underlying type system. In keeping with the
  621. Boost.Python philosophy, a Pyste interface description is neither
  622. intrusive on the code being wrapped, nor expressed in some unfamiliar
  623. language: instead it is a 100% pure Python script. If Pyste is
  624. successful it will mark a move away from wrapping everything directly
  625. in C++ for many of our users. It will also allow us the choice to
  626. shift some of the metaprogram code from C++ to Python. We expect that
  627. soon, not only our users but the Boost.Python developers themselves
  628. will be &quot;thinking hybrid&quot; about their own code.</p>
  629. </div>
  630. </div>
  631. <div class="section" id="serialization">
  632. <h2><a class="toc-backref" href="#id17">Serialization</a></h2>
  633. <p><em>Serialization</em> is the process of converting objects in memory to a
  634. form that can be stored on disk or sent over a network connection. The
  635. serialized object (most often a plain string) can be retrieved and
  636. converted back to the original object. A good serialization system will
  637. automatically convert entire object hierarchies. Python's standard
  638. <tt class="docutils literal">pickle</tt> module is just such a system. It leverages the language's strong
  639. runtime introspection facilities for serializing practically arbitrary
  640. user-defined objects. With a few simple and unintrusive provisions this
  641. powerful machinery can be extended to also work for wrapped C++ objects.
  642. Here is an example:</p>
  643. <pre class="literal-block">
  644. #include &lt;string&gt;
  645. struct World
  646. {
  647. World(std::string a_msg) : msg(a_msg) {}
  648. std::string greet() const { return msg; }
  649. std::string msg;
  650. };
  651. #include &lt;boost/python.hpp&gt;
  652. using namespace boost::python;
  653. struct World_picklers : pickle_suite
  654. {
  655. static tuple
  656. getinitargs(World const&amp; w) { return make_tuple(w.greet()); }
  657. };
  658. BOOST_PYTHON_MODULE(hello)
  659. {
  660. class_&lt;World&gt;(&quot;World&quot;, init&lt;std::string&gt;())
  661. .def(&quot;greet&quot;, &amp;World::greet)
  662. .def_pickle(World_picklers())
  663. ;
  664. }
  665. </pre>
  666. <p>Now let's create a <tt class="docutils literal">World</tt> object and put it to rest on disk:</p>
  667. <pre class="literal-block">
  668. &gt;&gt;&gt; import hello
  669. &gt;&gt;&gt; import pickle
  670. &gt;&gt;&gt; a_world = hello.World(&quot;howdy&quot;)
  671. &gt;&gt;&gt; pickle.dump(a_world, open(&quot;my_world&quot;, &quot;w&quot;))
  672. </pre>
  673. <p>In a potentially <em>different script</em> on a potentially <em>different
  674. computer</em> with a potentially <em>different operating system</em>:</p>
  675. <pre class="literal-block">
  676. &gt;&gt;&gt; import pickle
  677. &gt;&gt;&gt; resurrected_world = pickle.load(open(&quot;my_world&quot;, &quot;r&quot;))
  678. &gt;&gt;&gt; resurrected_world.greet()
  679. 'howdy'
  680. </pre>
  681. <p>Of course the <tt class="docutils literal">cPickle</tt> module can also be used for faster
  682. processing.</p>
  683. <p>Boost.Python's <tt class="docutils literal">pickle_suite</tt> fully supports the <tt class="docutils literal">pickle</tt> protocol
  684. defined in the standard Python documentation. Like a __getinitargs__
  685. function in Python, the pickle_suite's getinitargs() is responsible for
  686. creating the argument tuple that will be use to reconstruct the pickled
  687. object. The other elements of the Python pickling protocol,
  688. __getstate__ and __setstate__ can be optionally provided via C++
  689. getstate and setstate functions. C++'s static type system allows the
  690. library to ensure at compile-time that nonsensical combinations of
  691. functions (e.g. getstate without setstate) are not used.</p>
  692. <p>Enabling serialization of more complex C++ objects requires a little
  693. more work than is shown in the example above. Fortunately the
  694. <tt class="docutils literal">object</tt> interface (see next section) greatly helps in keeping the
  695. code manageable.</p>
  696. </div>
  697. <div class="section" id="object-interface">
  698. <h2><a class="toc-backref" href="#id18">Object interface</a></h2>
  699. <p>Experienced 'C' language extension module authors will be familiar
  700. with the ubiquitous <tt class="docutils literal">PyObject*</tt>, manual reference-counting, and the
  701. need to remember which API calls return &quot;new&quot; (owned) references or
  702. &quot;borrowed&quot; (raw) references. These constraints are not just
  703. cumbersome but also a major source of errors, especially in the
  704. presence of exceptions.</p>
  705. <p>Boost.Python provides a class <tt class="docutils literal">object</tt> which automates reference
  706. counting and provides conversion to Python from C++ objects of
  707. arbitrary type. This significantly reduces the learning effort for
  708. prospective extension module writers.</p>
  709. <p>Creating an <tt class="docutils literal">object</tt> from any other type is extremely simple:</p>
  710. <pre class="literal-block">
  711. object s(&quot;hello, world&quot;); // s manages a Python string
  712. </pre>
  713. <p><tt class="docutils literal">object</tt> has templated interactions with all other types, with
  714. automatic to-python conversions. It happens so naturally that it's
  715. easily overlooked:</p>
  716. <pre class="literal-block">
  717. object ten_Os = 10 * s[4]; // -&gt; &quot;oooooooooo&quot;
  718. </pre>
  719. <p>In the example above, <tt class="docutils literal">4</tt> and <tt class="docutils literal">10</tt> are converted to Python objects
  720. before the indexing and multiplication operations are invoked.</p>
  721. <p>The <tt class="docutils literal">extract&lt;T&gt;</tt> class template can be used to convert Python objects
  722. to C++ types:</p>
  723. <pre class="literal-block">
  724. double x = extract&lt;double&gt;(o);
  725. </pre>
  726. <p>If a conversion in either direction cannot be performed, an
  727. appropriate exception is thrown at runtime.</p>
  728. <p>The <tt class="docutils literal">object</tt> type is accompanied by a set of derived types
  729. that mirror the Python built-in types such as <tt class="docutils literal">list</tt>, <tt class="docutils literal">dict</tt>,
  730. <tt class="docutils literal">tuple</tt>, etc. as much as possible. This enables convenient
  731. manipulation of these high-level types from C++:</p>
  732. <pre class="literal-block">
  733. dict d;
  734. d[&quot;some&quot;] = &quot;thing&quot;;
  735. d[&quot;lucky_number&quot;] = 13;
  736. list l = d.keys();
  737. </pre>
  738. <p>This almost looks and works like regular Python code, but it is pure
  739. C++. Of course we can wrap C++ functions which accept or return
  740. <tt class="docutils literal">object</tt> instances.</p>
  741. </div>
  742. </div>
  743. <div class="section" id="thinking-hybrid">
  744. <h1><a class="toc-backref" href="#id19">Thinking hybrid</a></h1>
  745. <p>Because of the practical and mental difficulties of combining
  746. programming languages, it is common to settle a single language at the
  747. outset of any development effort. For many applications, performance
  748. considerations dictate the use of a compiled language for the core
  749. algorithms. Unfortunately, due to the complexity of the static type
  750. system, the price we pay for runtime performance is often a
  751. significant increase in development time. Experience shows that
  752. writing maintainable C++ code usually takes longer and requires <em>far</em>
  753. more hard-earned working experience than developing comparable Python
  754. code. Even when developers are comfortable working exclusively in
  755. compiled languages, they often augment their systems by some type of
  756. ad hoc scripting layer for the benefit of their users without ever
  757. availing themselves of the same advantages.</p>
  758. <p>Boost.Python enables us to <em>think hybrid</em>. Python can be used for
  759. rapidly prototyping a new application; its ease of use and the large
  760. pool of standard libraries give us a head start on the way to a
  761. working system. If necessary, the working code can be used to
  762. discover rate-limiting hotspots. To maximize performance these can
  763. be reimplemented in C++, together with the Boost.Python bindings
  764. needed to tie them back into the existing higher-level procedure.</p>
  765. <p>Of course, this <em>top-down</em> approach is less attractive if it is clear
  766. from the start that many algorithms will eventually have to be
  767. implemented in C++. Fortunately Boost.Python also enables us to
  768. pursue a <em>bottom-up</em> approach. We have used this approach very
  769. successfully in the development of a toolbox for scientific
  770. applications. The toolbox started out mainly as a library of C++
  771. classes with Boost.Python bindings, and for a while the growth was
  772. mainly concentrated on the C++ parts. However, as the toolbox is
  773. becoming more complete, more and more newly added functionality can be
  774. implemented in Python.</p>
  775. <img alt="images/python_cpp_mix.png" src="images/python_cpp_mix.png" />
  776. <p>This figure shows the estimated ratio of newly added C++ and Python
  777. code over time as new algorithms are implemented. We expect this
  778. ratio to level out near 70% Python. Being able to solve new problems
  779. mostly in Python rather than a more difficult statically typed
  780. language is the return on our investment in Boost.Python. The ability
  781. to access all of our code from Python allows a broader group of
  782. developers to use it in the rapid development of new applications.</p>
  783. </div>
  784. <div class="section" id="development-history">
  785. <h1><a class="toc-backref" href="#id20">Development history</a></h1>
  786. <p>The first version of Boost.Python was developed in 2000 by Dave
  787. Abrahams at Dragon Systems, where he was privileged to have Tim Peters
  788. as a guide to &quot;The Zen of Python&quot;. One of Dave's jobs was to develop
  789. a Python-based natural language processing system. Since it was
  790. eventually going to be targeting embedded hardware, it was always
  791. assumed that the compute-intensive core would be rewritten in C++ to
  792. optimize speed and memory footprint<a class="footnote-reference" href="#proto" id="id2"><sup>1</sup></a>. The project also wanted to
  793. test all of its C++ code using Python test scripts<a class="footnote-reference" href="#test" id="id3"><sup>2</sup></a>. The only
  794. tool we knew of for binding C++ and Python was <a class="reference external" href="http://www.swig.org/">SWIG</a>, and at the time
  795. its handling of C++ was weak. It would be false to claim any deep
  796. insight into the possible advantages of Boost.Python's approach at
  797. this point. Dave's interest and expertise in fancy C++ template
  798. tricks had just reached the point where he could do some real damage,
  799. and Boost.Python emerged as it did because it filled a need and
  800. because it seemed like a cool thing to try.</p>
  801. <p>This early version was aimed at many of the same basic goals we've
  802. described in this paper, differing most-noticeably by having a
  803. slightly more cumbersome syntax and by lack of special support for
  804. operator overloading, pickling, and component-based development.
  805. These last three features were quickly added by Ullrich Koethe and
  806. Ralf Grosse-Kunstleve<a class="footnote-reference" href="#feature" id="id4"><sup>3</sup></a>, and other enthusiastic contributors arrived
  807. on the scene to contribute enhancements like support for nested
  808. modules and static member functions.</p>
  809. <p>By early 2001 development had stabilized and few new features were
  810. being added, however a disturbing new fact came to light: Ralf had
  811. begun testing Boost.Python on pre-release versions of a compiler using
  812. the <a class="reference external" href="http://www.edg.com">EDG</a> front-end, and the mechanism at the core of Boost.Python
  813. responsible for handling conversions between Python and C++ types was
  814. failing to compile. As it turned out, we had been exploiting a very
  815. common bug in the implementation of all the C++ compilers we had
  816. tested. We knew that as C++ compilers rapidly became more
  817. standards-compliant, the library would begin failing on more
  818. platforms. Unfortunately, because the mechanism was so central to the
  819. functioning of the library, fixing the problem looked very difficult.</p>
  820. <p>Fortunately, later that year Lawrence Berkeley and later Lawrence
  821. Livermore National labs contracted with <a class="reference external" href="http://www.boost-consulting.com">Boost Consulting</a> for support
  822. and development of Boost.Python, and there was a new opportunity to
  823. address fundamental issues and ensure a future for the library. A
  824. redesign effort began with the low level type conversion architecture,
  825. building in standards-compliance and support for component-based
  826. development (in contrast to version 1 where conversions had to be
  827. explicitly imported and exported across module boundaries). A new
  828. analysis of the relationship between the Python and C++ objects was
  829. done, resulting in more intuitive handling for C++ lvalues and
  830. rvalues.</p>
  831. <p>The emergence of a powerful new type system in Python 2.2 made the
  832. choice of whether to maintain compatibility with Python 1.5.2 easy:
  833. the opportunity to throw away a great deal of elaborate code for
  834. emulating classic Python classes alone was too good to pass up. In
  835. addition, Python iterators and descriptors provided crucial and
  836. elegant tools for representing similar C++ constructs. The
  837. development of the generalized <tt class="docutils literal">object</tt> interface allowed us to
  838. further shield C++ programmers from the dangers and syntactic burdens
  839. of the Python 'C' API. A great number of other features including C++
  840. exception translation, improved support for overloaded functions, and
  841. most significantly, CallPolicies for handling pointers and
  842. references, were added during this period.</p>
  843. <p>In October 2002, version 2 of Boost.Python was released. Development
  844. since then has concentrated on improved support for C++ runtime
  845. polymorphism and smart pointers. Peter Dimov's ingenious
  846. <tt class="docutils literal"><span class="pre">boost::shared_ptr</span></tt> design in particular has allowed us to give the
  847. hybrid developer a consistent interface for moving objects back and
  848. forth across the language barrier without loss of information. At
  849. first, we were concerned that the sophistication and complexity of the
  850. Boost.Python v2 implementation might discourage contributors, but the
  851. emergence of <a class="reference external" href="http://www.boost.org/libs/python/pyste">Pyste</a> and several other significant feature
  852. contributions have laid those fears to rest. Daily questions on the
  853. Python C++-sig and a backlog of desired improvements show that the
  854. library is getting used. To us, the future looks bright.</p>
  855. </div>
  856. <div class="section" id="conclusions">
  857. <h1><a class="toc-backref" href="#id21">Conclusions</a></h1>
  858. <p>Boost.Python achieves seamless interoperability between two rich and
  859. complimentary language environments. Because it leverages template
  860. metaprogramming to introspect about types and functions, the user
  861. never has to learn a third syntax: the interface definitions are
  862. written in concise and maintainable C++. Also, the wrapping system
  863. doesn't have to parse C++ headers or represent the type system: the
  864. compiler does that work for us.</p>
  865. <p>Computationally intensive tasks play to the strengths of C++ and are
  866. often impossible to implement efficiently in pure Python, while jobs
  867. like serialization that are trivial in Python can be very difficult in
  868. pure C++. Given the luxury of building a hybrid software system from
  869. the ground up, we can approach design with new confidence and power.</p>
  870. </div>
  871. <div class="section" id="citations">
  872. <h1><a class="toc-backref" href="#id22">Citations</a></h1>
  873. <table class="docutils citation" frame="void" id="veld1995" rules="none">
  874. <colgroup><col class="label" /><col /></colgroup>
  875. <tbody valign="top">
  876. <tr><td class="label"><a class="fn-backref" href="#id1">[VELD1995]</a></td><td>T. Veldhuizen, &quot;Expression Templates,&quot; C++ Report,
  877. Vol. 7 No. 5 June 1995, pp. 26-31.
  878. <a class="reference external" href="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html</a></td></tr>
  879. </tbody>
  880. </table>
  881. </div>
  882. <div class="section" id="footnotes">
  883. <h1><a class="toc-backref" href="#id23">Footnotes</a></h1>
  884. <table class="docutils footnote" frame="void" id="proto" rules="none">
  885. <colgroup><col class="label" /><col /></colgroup>
  886. <tbody valign="top">
  887. <tr><td class="label"><a class="fn-backref" href="#id2">[1]</a></td><td>In retrospect, it seems that &quot;thinking hybrid&quot; from the
  888. ground up might have been better for the NLP system: the
  889. natural component boundaries defined by the pure python
  890. prototype turned out to be inappropriate for getting the
  891. desired performance and memory footprint out of the C++ core,
  892. which eventually caused some redesign overhead on the Python
  893. side when the core was moved to C++.</td></tr>
  894. </tbody>
  895. </table>
  896. <table class="docutils footnote" frame="void" id="test" rules="none">
  897. <colgroup><col class="label" /><col /></colgroup>
  898. <tbody valign="top">
  899. <tr><td class="label"><a class="fn-backref" href="#id3">[2]</a></td><td>We also have some reservations about driving all C++
  900. testing through a Python interface, unless that's the only way
  901. it will be ultimately used. Any transition across language
  902. boundaries with such different object models can inevitably
  903. mask bugs.</td></tr>
  904. </tbody>
  905. </table>
  906. <table class="docutils footnote" frame="void" id="feature" rules="none">
  907. <colgroup><col class="label" /><col /></colgroup>
  908. <tbody valign="top">
  909. <tr><td class="label"><a class="fn-backref" href="#id4">[3]</a></td><td>These features were expressed very differently in v1 of
  910. Boost.Python</td></tr>
  911. </tbody>
  912. </table>
  913. </div>
  914. </div>
  915. </body>
  916. </html>