Skip to content

Commit eedea9c

Browse files
committed
Finished draft. Ready for proof-reading.
[SVN r751]
1 parent 567802f commit eedea9c

4 files changed

Lines changed: 327 additions & 116 deletions

File tree

doc/tutorial/doc/embedding.html

Lines changed: 8 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
44
<title>Embedding</title>
55
<link rel="stylesheet" href="theme/style.css" type="text/css">
6+
<link rel="next" href="embedding_basics.html">
67
</head>
78
<body>
89
<table width="100%" height="48" border="0" background="theme/bkd2.gif" cellspacing="2">
@@ -20,106 +21,23 @@
2021
<tr>
2122
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
2223
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
23-
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
24+
<td width="20"><a href="embedding_basics.html"><img src="theme/r_arr.gif" border="0"></a></td>
2425
</tr>
2526
</table>
26-
<a name="embedding_basics"></a><h2>Embedding basics</h2><p>
27+
<a name="getting_started"></a><h2>Getting started</h2><p>
2728
By now you should know how to use Boost.Python to call your C++ code from Python. However sometimes you might need to do the reverse: call Python code from the C++-side. This requires you to 'embed' the Python interpreter in your C++ program. For this we need to use the <a href="http://www.python.org/doc/current/api/api.html">
2829
Python C API</a>.</p>
2930
<p>
30-
The basics to embedding with the API are pretty simple. First you need to make sure that your program links with <tt>pythonXY.lib</tt> where X.Y is your Python version number. You'll typically find this library in the libs subdirectory of your Python installation. Now your program can follow these steps:</p>
31-
<ol><li>#include <tt>&quot;Python.h&quot;</tt></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
32-
Py_Initialize</a>() to start the Python interpreter.</li><li>Call other Python C API routines. </li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
31+
To get started you'll need to follow these simple steps:</p>
32+
<ol><li>You need to make sure that your program links with <tt>pythonXY.lib</tt> where X.Y is your Python version number. You'll typically find this library in the <tt>/libs</tt> subdirectory of your Python installation.<br><br></li><li>Your program must #include <tt>&quot;Python.h&quot;</tt>. You'll need to add Python's <tt>/include</tt> subdirectory to your include path for this.<br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
33+
Py_Initialize</a>() to start the Python interpreter. Also creates the <tt>__main__</tt> module.<br><br></li><li>Call other Python C API routines.<br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
3334
Py_Finalize</a>() to stop the Python interpreter and release its resources.</li></ol><p>
3435
Of course, there can be other C++ code between all of these steps.</p>
35-
<p>
36-
Now this looks pretty simple, but we'll see in the next section that step 3 can be tricky.</p>
37-
<a name="manual_reference_counting"></a><h2>Manual reference counting</h2><p>
38-
Most things in Python are objects. Therefore it is only natural that many of the Python C API functions operate on Python objects. Because C/C++ can't work with Python objects directly, the API defines a PyObject structure and a lot of functions to operate on PyObject pointers. </p>
39-
<p>
40-
An important property of Python objects, and therefore of PyObjects, is that they are reference counted. This has major advantages compared to 'dumb' copying: it requiring less memory and it avoids unnecessary copying overhead. However, there is a downside as well. Although the reference counting is transparent from the Python-side, it is quite explicit in the C API. In other words you must increase and decrease the reference counts of PyObjects <b>manually</b> using the <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-65">
41-
Py_XINCREF</a> and <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-67">
42-
Py_XDECREF</a> macros. This is cumbersome, and if you don't do it properly some objects might be released when you still need them, or not be released at all. </p>
43-
<p>
44-
I will briefly explain how to update the reference counts correctly, but I'll soon show a better way to do things.</p>
45-
<p>
46-
The API functions that return PyObject pointers are listed in the Python C API documentation as either returning a <i>borrowed</i> or a <i>new</i> reference. The difference is in <i>reference ownership</i>. </p>
47-
<p>
48-
When a <i>new</i> reference is returned, you own that reference. Therefore you don't need to worry about the object being deallocated while you still need it. You do need to decrease the reference count when you are done with it however, otherwise the object will never be deallocated. In other words, you'll have a resource leak. </p>
49-
<p>
50-
Here's a simple example:</p>
51-
<blockquote><p><b>TODO:</b> <tt>need different examples because the current ones can be done very naturally with python::tuple which makes them rather unsuitable for explaining python::<a href="../../v2/handle.html">
52-
handle</a> </tt></p></blockquote><code><pre>
53-
<span class=comment>// Create a new tuple of 3 elements long
54-
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>my_tuple </span><span class=special>= </span><span class=identifier>PyTuple_New</span><span class=special>(</span><span class=number>3</span><span class=special>);
55-
</span><span class=special>... </span><span class=comment>// Use my_tuple here
56-
// We're done with the tuple
57-
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>my_tuple</span><span class=special>);
58-
</span></pre></code>
59-
<p>
60-
When a <i>borrowed</i> reference is returned, you do not have ownership of the reference. So if you just want to discard the return value, there is nothing you have to do: you didn't own it anyway. If want to use it however, you'll first have to increase its reference count (to prevent the objects deletion). Then later on when you are done with itm you'll need to decrease the reference count again. Here's another example:</p>
61-
<code><pre>
62-
<span class=comment>// Retrieve the first item in the tuple
63-
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>first </span><span class=special>= </span><span class=identifier>PyTuple_GetItem</span><span class=special>(</span><span class=identifier>my_tuple</span><span class=special>, </span><span class=number>0</span><span class=special>);
64-
</span><span class=identifier>Py_XINCREF</span><span class=special>(</span><span class=identifier>first</span><span class=special>);
65-
</span><span class=special>... </span><span class=comment>// Use first here
66-
// We're done with the first tuple item
67-
</span><span class=identifier>Py_XDECREF</span><span class=special>(</span><span class=identifier>first</span><span class=special>);
68-
</span></pre></code>
69-
<p>
70-
While this certainly works, it's hardly elegant and it's easy to make mistakes, especially when there are multiple execution paths.</p>
71-
<a name="boost_python_to_the_rescue"></a><h2>Boost.Python to the rescue</h2><p>
72-
Now we get to the good news. If you don't want to do all the error prone reference counting yourself, you can let Boost.Python do all the work. First include <tt>&lt;boost/python.hpp&gt;</tt> instead of <tt>&quot;Python.h&quot;</tt> and link to <tt>boost_python.lib</tt> (or <tt>boost_python_debug.lib</tt>) instead of <tt>pythonXY.lib</tt>. Then all we really need to do is replace every PyObject* with <a href="../../v2/handle.html">
73-
handle</a>&lt;PyObject&gt; and we can remove all the <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-65">
74-
Py_XINCREF</a>s and <a href="http://www.python.org/doc/current/api/countingRefs.html#l2h-67">
75-
Py_XDECREF</a>s! All the reference counting will be done automagically through the power of the <a href="http://sourceforge.net/docman/display_doc.php?docid=8673&amp;group_id=9028">
76-
Resource Acquisition Is Initialization</a> idiom. </p>
77-
<p>
78-
We still need a way to differentiate between new and borrowed references though. Luckily, this is pretty straightforward using the <a href="../../v2/handle.html#borrowed-spec">
79-
borrowed</a> function. Here is an example using <a href="../../v2/handle.html">
80-
handle</a> that combines the functionality of the above two PyObject* examples. Notice how it is both shorter and cleaner:</p>
81-
<code><pre>
82-
<span class=comment>// Create a new tuple of 3 elements long
83-
</span><span class=identifier>handle</span><span class=special>&lt;</span><span class=identifier>PyObject</span><span class=special>&gt; </span><span class=identifier>my_tuple</span><span class=special>( </span><span class=identifier>PyTuple_New</span><span class=special>(</span><span class=number>3</span><span class=special>) </span><span class=special>);
84-
</span><span class=comment>// Retrieve the first item in the tuple
85-
</span><span class=identifier>handle</span><span class=special>&lt;</span><span class=identifier>PyObject</span><span class=special>&gt; </span><span class=identifier>first</span><span class=special>( </span><span class=identifier>borrowed</span><span class=special>(</span><span class=identifier>PyTuple_GetItem</span><span class=special>(</span><span class=identifier>my_tuple</span><span class=special>.</span><span class=identifier>get</span><span class=special>(), </span><span class=number>0</span><span class=special>)) </span><span class=special>);
86-
</span><span class=special>... </span><span class=comment>// Use first here
87-
</span></pre></code>
88-
<p>
89-
Note that the <a href="../../v2/handle.html">
90-
handle</a> member function get() returns the raw PyObject* that is held by the <a href="../../v2/handle.html">
91-
handle</a>. </p>
92-
<blockquote><p><b>TODO:</b> <tt>Explain PyRun_... basics, somewhere. Perhaps these functions can be used in the examples?</tt></p></blockquote><a name="boost_python_modules_in_an_embedded_program"></a><h2>Boost.Python modules in an embedded program</h2><p>
93-
Now that we know how to call Python code from C++ and C++ code from Python, how about doing it both at the same time? Sometimes you might want to call Python code from C++ and have that Python code call C++ code again. If you built your Boost.Python module then you can just use it in your embedded Python code as you would in a standalone Python program: no further changes necessary.</p>
94-
<p>
95-
However, you can also define the Boost.Python module in the same program that embeds the Python code which will be using the module. Then you won't have to build the module and place it in the proper directory, and this also prevents others from using it in their own Python code. (Unless they start taking your executable apart that is. <img src="theme/smiley.gif"></img>) </p>
96-
<p>
97-
Doing this is relatively straightforward. You just define your Boost.Python module as usual and use the basic embedding steps described above. However, before calling <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
98-
Py_Initialize</a> you call <a href="http://www.python.org/doc/current/api/importing.html#l2h-137">
99-
PyImport_AppendInittab</a> first. This function takes the name and initialization function of your module as parameters and adds the module to the interpreters list of builtin modules. So when the Python interpreter comes across an import statement, it will find the module in its list of builtin modules instead of (unsuccessfully) searching for it in the Python directory.</p>
100-
<p>
101-
Your program will look something like this:</p>
102-
<code><pre>
103-
<span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>my_module</span><span class=special>)
104-
</span><span class=special>{
105-
</span><span class=special>...
106-
</span><span class=special>}
107-
</span><span class=special>...
108-
</span><span class=identifier>PyImport_AppendInittab</span><span class=special>(</span><span class=string>&quot;my_module&quot;</span><span class=special>, </span><span class=identifier>initmy_module</span><span class=special>);
109-
</span><span class=identifier>Py_Initialize</span><span class=special>();
110-
</span><span class=special>...
111-
</span></pre></code>
112-
<p>
113-
There is one catch at the moment though. You must <b>not</b> call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
114-
Py_Finalize</a>. Boost.Python keeps some PyObject references alive in global data structures, and when those go out of scope after interpreter finalization, Python crashes. This will be fixed in the future. </p>
115-
<a name="additional_reading"></a><h2>Additional reading</h2><p>
116-
A more elaborate example showing these techniques is located at <a href="../../../test/embedding.cpp">
117-
libs/python/test/embedding.cpp</a>. </p>
118-
<table border="0">
36+
<blockquote><p><b>TODO:</b> <tt>Perhaps there should be a template Jamfile for embedding? Then we can put (a link to) it here.</tt></p></blockquote><blockquote><p><i><b>Now that we can embed the interpreter in our programs, lets see how to put it to use...</b></i></p></blockquote><table border="0">
11937
<tr>
12038
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
12139
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
122-
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
40+
<td width="20"><a href="embedding_basics.html"><img src="theme/r_arr.gif" border="0"></a></td>
12341
</tr>
12442
</table>
12543
<br>

0 commit comments

Comments
 (0)