• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Chapter 8. Topics</title>
5<link rel="stylesheet" href="../boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="index.html" title="Boost.Python Reference Manual">
8<link rel="up" href="index.html" title="Boost.Python Reference Manual">
9<link rel="prev" href="utility_and_infrastructure/boost_python_ssize_t_hpp.html" title="boost/python/ssize_t.hpp">
10<link rel="next" href="topics/pickle_support.html" title="Pickle support">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="" width="" height="" src="../images/boost.png"></td></tr></table>
14<hr>
15<div class="spirit-nav">
16<a accesskey="p" href="utility_and_infrastructure/boost_python_ssize_t_hpp.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="topics/pickle_support.html"><img src="../images/next.png" alt="Next"></a>
17</div>
18<div class="chapter">
19<div class="titlepage"><div><div><h1 class="title">
20<a name="topics"></a>Chapter 8. Topics</h1></div></div></div>
21<div class="toc">
22<p><b>Table of Contents</b></p>
23<dl class="toc">
24<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met">Calling Python
25      Functions and Methods</a></span></dt>
26<dd><dl>
27<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.introduction">Introduction</a></span></dt>
28<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.argument_handling">Argument
29        Handling</a></span></dt>
30<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.result_handling">Result
31        Handling</a></span></dt>
32<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.rationale">Rationale</a></span></dt>
33</dl></dd>
34<dt><span class="section"><a href="topics/pickle_support.html">Pickle support</a></span></dt>
35<dd><dl>
36<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.introduction">Introduction</a></span></dt>
37<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.the_pickle_interface">The Pickle
38        Interface</a></span></dt>
39<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.example">Example</a></span></dt>
40<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.pitfall_and_safety_guard">Pitfall
41        and Safety Guard</a></span></dt>
42<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.practical_advice">Practical Advice</a></span></dt>
43<dt><span class="section"><a href="topics/pickle_support.html#topics.pickle_support.light_weight_alternative_pickle_">Light-weight
44        alternative: pickle support implemented in Python</a></span></dt>
45</dl></dd>
46<dt><span class="section"><a href="topics/indexing_support.html">Indexing support</a></span></dt>
47<dd><dl>
48<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.introduction">Introduction</a></span></dt>
49<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.the_indexing_interface">The
50        Indexing Interface</a></span></dt>
51<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.index_suite_sub_classes">index_suite
52        sub-classes</a></span></dt>
53<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.indexing_suite_class"><code class="computeroutput"><span class="identifier">indexing_suite</span></code> class</a></span></dt>
54<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.class_vector_indexing_suite">class
55        <code class="computeroutput"><span class="identifier">vector_indexing_suite</span></code></a></span></dt>
56<dt><span class="section"><a href="topics/indexing_support.html#topics.indexing_support.class_map_indexing_suite">class
57        <code class="computeroutput"><span class="identifier">map_indexing_suite</span></code></a></span></dt>
58</dl></dd>
59</dl>
60</div>
61<div class="section">
62<div class="titlepage"><div><div><h2 class="title" style="clear: both">
63<a name="topics.calling_python_functions_and_met"></a><a class="link" href="topics.html#topics.calling_python_functions_and_met" title="Calling Python Functions and Methods">Calling Python
64      Functions and Methods</a>
65</h2></div></div></div>
66<div class="toc"><dl class="toc">
67<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.introduction">Introduction</a></span></dt>
68<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.argument_handling">Argument
69        Handling</a></span></dt>
70<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.result_handling">Result
71        Handling</a></span></dt>
72<dt><span class="section"><a href="topics.html#topics.calling_python_functions_and_met.rationale">Rationale</a></span></dt>
73</dl></div>
74<div class="section">
75<div class="titlepage"><div><div><h3 class="title">
76<a name="topics.calling_python_functions_and_met.introduction"></a><a class="link" href="topics.html#topics.calling_python_functions_and_met.introduction" title="Introduction">Introduction</a>
77</h3></div></div></div>
78<p>
79          The simplest way to call a Python function from C++, given an <a class="link" href="object_wrappers/boost_python_object_hpp.html#object_wrappers.boost_python_object_hpp.class_object" title="Class object"><code class="computeroutput"><span class="identifier">object</span></code></a> instance f holding the
80          function, is simply to invoke its function call operator.
81        </p>
82<pre class="programlisting"><span class="identifier">f</span><span class="special">(</span><span class="string">"tea"</span><span class="special">,</span> <span class="number">4</span><span class="special">,</span> <span class="number">2</span><span class="special">)</span> <span class="comment">// In Python: f('tea', 4, 2)</span></pre>
83<p>
84          And of course, a method of an <a class="link" href="object_wrappers/boost_python_object_hpp.html#object_wrappers.boost_python_object_hpp.class_object" title="Class object"><code class="computeroutput"><span class="identifier">object</span></code></a> instance <code class="computeroutput"><span class="identifier">x</span></code> can be invoked by using the function-call
85          operator of the corresponding attribute:
86        </p>
87<pre class="programlisting"><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"tea"</span><span class="special">)(</span><span class="number">4</span><span class="special">,</span> <span class="number">2</span><span class="special">);</span> <span class="comment">// In Python: x.tea(4, 2)</span></pre>
88<p>
89          If you don't have an <a class="link" href="object_wrappers/boost_python_object_hpp.html#object_wrappers.boost_python_object_hpp.class_object" title="Class object"><code class="computeroutput"><span class="identifier">object</span></code></a> instance, <code class="computeroutput"><span class="identifier">Boost</span><span class="special">.</span><span class="identifier">Python</span></code> provides two families of function
90          templates, <a class="link" href="function_invocation_and_creation/boost_python_call_hpp.html#function_invocation_and_creation.boost_python_call_hpp.function_call" title="Function call"><code class="computeroutput"><span class="identifier">call</span></code></a> and <a class="link" href="function_invocation_and_creation/boost_python_call_method_hpp.html#function_invocation_and_creation.boost_python_call_method_hpp.function_call_method" title="Function call_method"><code class="computeroutput"><span class="identifier">call_method</span></code></a>, for invoking Python
91          functions and methods respectively on <code class="computeroutput"><span class="identifier">PyObject</span><span class="special">*</span></code>s. The interface for calling a Python function
92          object (or any Python callable object) looks like:
93        </p>
94<pre class="programlisting"><span class="identifier">call</span><span class="special">&lt;</span><span class="identifier">ResultType</span><span class="special">&gt;(</span><span class="identifier">callable_object</span><span class="special">,</span> <span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">...</span> <span class="identifier">aN</span><span class="special">);</span></pre>
95<p>
96          Calling a method of a Python object is similarly easy:
97        </p>
98<pre class="programlisting"><span class="identifier">call_method</span><span class="special">&lt;</span><span class="identifier">ResultType</span><span class="special">&gt;(</span><span class="identifier">self_object</span><span class="special">,</span> <span class="string">"method-name"</span><span class="special">,</span> <span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">...</span> <span class="identifier">aN</span><span class="special">);</span></pre>
99<p>
100          This comparitively low-level interface is the one you'll use when implementing
101          C++ virtual functions that can be overridden in Python.
102        </p>
103</div>
104<div class="section">
105<div class="titlepage"><div><div><h3 class="title">
106<a name="topics.calling_python_functions_and_met.argument_handling"></a><a class="link" href="topics.html#topics.calling_python_functions_and_met.argument_handling" title="Argument Handling">Argument
107        Handling</a>
108</h3></div></div></div>
109<p>
110          Arguments are converted to Python according to their type. By default,
111          the arguments <code class="computeroutput"><span class="identifier">a1</span><span class="special">...</span><span class="identifier">aN</span></code> are copied into new Python objects,
112          but this behavior can be overridden by the use of <a class="link" href="function_invocation_and_creation/boost_python_ptr_hpp.html#function_invocation_and_creation.boost_python_ptr_hpp.functions" title="Functions"><code class="computeroutput"><span class="identifier">ptr</span><span class="special">()</span></code></a>
113          and <code class="computeroutput"><span class="identifier">ref</span><span class="special">()</span></code>:
114        </p>
115<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">X</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span>
116<span class="special">{</span>
117   <span class="special">...</span>
118<span class="special">};</span>
119
120<span class="keyword">void</span> <span class="identifier">apply</span><span class="special">(</span><span class="identifier">PyObject</span><span class="special">*</span> <span class="identifier">callable</span><span class="special">,</span> <span class="identifier">X</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">)</span>
121<span class="special">{</span>
122   <span class="comment">// Invoke callable, passing a Python object which holds a reference to x</span>
123   <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">::</span><span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;(</span><span class="identifier">callable</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">));</span>
124<span class="special">}</span>
125</pre>
126<p>
127          In the table below, x denotes the actual argument object and cv denotes
128          an optional cv-qualification: "const", "volatile",
129          or "const volatile".
130        </p>
131<div class="informaltable"><table class="table">
132<colgroup>
133<col>
134<col>
135</colgroup>
136<thead><tr>
137<th>
138                  <p>
139                    Argument Type
140                  </p>
141                </th>
142<th>
143                  <p>
144                    Behavior
145                  </p>
146                </th>
147</tr></thead>
148<tbody>
149<tr>
150<td>
151                  <p>
152                    <code class="computeroutput"><span class="identifier">T</span> <span class="identifier">cv</span>
153                    <span class="special">&amp;</span></code> <code class="computeroutput"><span class="identifier">T</span>
154                    <span class="identifier">cv</span></code>
155                  </p>
156                </td>
157<td>
158                  <p>
159                    The Python argument is created by the same means used for the
160                    return value of a wrapped C++ function returning T. When T is
161                    a class type, that normally means *x is copy-constructed into
162                    the new Python object.
163                  </p>
164                </td>
165</tr>
166<tr>
167<td>
168                  <p>
169                    T*
170                  </p>
171                </td>
172<td>
173                  <p>
174                    If x == 0, the Python argument will be None. Otherwise, the Python
175                    argument is created by the same means used for the return value
176                    of a wrapped C++ function returning T. When T is a class type,
177                    that normally means *x is copy-constructed into the new Python
178                    object.
179                  </p>
180                </td>
181</tr>
182<tr>
183<td>
184                  <p>
185                    boost::reference_wrapper&lt;T&gt;
186                  </p>
187                </td>
188<td>
189                  <p>
190                    The Python argument contains a pointer to, rather than a copy
191                    of, x.get(). Note: failure to ensure that no Python code holds
192                    a reference to the resulting object beyond the lifetime of *x.get()
193                    may result in a crash!
194                  </p>
195                </td>
196</tr>
197<tr>
198<td>
199                  <p>
200                    pointer_wrapper&lt;T&gt;
201                  </p>
202                </td>
203<td>
204                  <p>
205                    If x.get() == 0, the Python argument will be None. Otherwise,
206                    the Python argument contains a pointer to, rather than a copy
207                    of, *x.get(). Note: failure to ensure that no Python code holds
208                    a reference to the resulting object beyond the lifetime of *x.get()
209                    may result in a crash!
210                  </p>
211                </td>
212</tr>
213</tbody>
214</table></div>
215</div>
216<div class="section">
217<div class="titlepage"><div><div><h3 class="title">
218<a name="topics.calling_python_functions_and_met.result_handling"></a><a class="link" href="topics.html#topics.calling_python_functions_and_met.result_handling" title="Result Handling">Result
219        Handling</a>
220</h3></div></div></div>
221<p>
222          In general, <code class="computeroutput"><span class="identifier">call</span><span class="special">&lt;</span><span class="identifier">ResultType</span><span class="special">&gt;()</span></code>
223          and call_method&lt;ResultType&gt;() return ResultType by exploiting all
224          lvalue and rvalue from_python converters registered for ResultType and
225          returning a copy of the result. However, when ResultType is a pointer or
226          reference type, Boost.Python searches only for lvalue converters. To prevent
227          dangling pointers and references, an exception will be thrown if the Python
228          result object has only a single reference count.
229        </p>
230</div>
231<div class="section">
232<div class="titlepage"><div><div><h3 class="title">
233<a name="topics.calling_python_functions_and_met.rationale"></a><a class="link" href="topics.html#topics.calling_python_functions_and_met.rationale" title="Rationale">Rationale</a>
234</h3></div></div></div>
235<p>
236          In general, to get Python arguments corresponding to a1...aN, a new Python
237          object must be created for each one; should the C++ object be copied into
238          that Python object, or should the Python object simply hold a reference/pointer
239          to the C++ object? In general, the latter approach is unsafe, since the
240          called function may store a reference to the Python object somewhere. If
241          the Python object is used after the C++ object is destroyed, we'll crash
242          Python.
243        </p>
244<p>
245          In keeping with the philosophy that users on the Python side shouldn't
246          have to worry about crashing the interpreter, the default behavior is to
247          copy the C++ object, and to allow a non-copying behavior only if the user
248          writes boost::ref(a1) instead of a1 directly. At least this way, the user
249          doesn't get dangerous behavior "by accident". It's also worth
250          noting that the non-copying ("by-reference") behavior is in general
251          only available for class types, and will fail at runtime with a Python
252          exception if used otherwise[1].
253        </p>
254<p>
255          However, pointer types present a problem: one approach is to refuse to
256          compile if any aN has pointer type: after all, a user can always pass *aN
257          to pass "by-value" or ref(*aN) to indicate a pass-by-reference
258          behavior. However, this creates a problem for the expected null pointer
259          to None conversion: it's illegal to dereference a null pointer value.
260        </p>
261<p>
262          The compromise I've settled on is this:
263        </p>
264<div class="orderedlist"><ol class="orderedlist" type="1">
265<li class="listitem">
266              The default behavior is pass-by-value. If you pass a non-null pointer,
267              the pointee is copied into a new Python object; otherwise the corresponding
268              Python argument will be None.
269            </li>
270<li class="listitem">
271              if you want by-reference behavior, use ptr(aN) if aN is a pointer and
272              ref(aN) otherwise. If a null pointer is passed to ptr(aN), the corresponding
273              Python argument will be None.
274            </li>
275</ol></div>
276<p>
277          As for results, we have a similar problem: if ResultType is allowed to
278          be a pointer or reference type, the lifetime of the object it refers to
279          is probably being managed by a Python object. When that Python object is
280          destroyed, our pointer dangles. The problem is particularly bad when the
281          ResultType is char const* - the corresponding Python String object is typically
282          uniquely-referenced, meaning that the pointer dangles as soon as call&lt;char
283          const*&gt;(...) returns.
284        </p>
285<p>
286          The old Boost.Python v1 deals with this issue by refusing to compile any
287          uses of call&lt;char const*&gt;(), but this goes both too far and not far
288          enough. It goes too far because there are cases where the owning Python
289          string object survives beyond the call (just for instance, when it's the
290          name of a Python class), and it goes not far enough because we might just
291          as well have the same problem with a returned pointer or reference of any
292          other type.
293        </p>
294<p>
295          In Boost.Python this is dealt with by:
296        </p>
297<div class="orderedlist"><ol class="orderedlist" type="1">
298<li class="listitem">
299              lifting the compile-time restriction on <code class="computeroutput"><span class="keyword">char</span>
300              <span class="keyword">const</span> <span class="special">*</span></code>
301              callback returns
302            </li>
303<li class="listitem">
304              detecting the case when the reference count on the result Python object
305              is 1 and throwing an exception inside of <code class="computeroutput"><span class="identifier">call</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;(...)</span></code> when <code class="computeroutput"><span class="identifier">U</span></code>
306              is a pointer or reference type.
307            </li>
308</ol></div>
309<p>
310          This should be acceptably safe because users have to explicitly specify
311          a pointer/reference for <code class="computeroutput"><span class="identifier">U</span></code>
312          in <code class="computeroutput"><span class="identifier">call</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span></code>,
313          and they will be protected against dangles at runtime, at least long enough
314          to get out of the <code class="computeroutput"><span class="identifier">call</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;(...)</span></code> invocation.
315        </p>
316</div>
317</div>
318</div>
319<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
320<td align="left"></td>
321<td align="right"><div class="copyright-footer">Copyright © 2002-2005, 2015 David Abrahams, Stefan Seefeld<p>
322        Distributed under the Boost Software License, Version 1.0. (See accompanying
323        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>
324      </p>
325</div></td>
326</tr></table>
327<hr>
328<div class="spirit-nav">
329<a accesskey="p" href="utility_and_infrastructure/boost_python_ssize_t_hpp.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="topics/pickle_support.html"><img src="../images/next.png" alt="Next"></a>
330</div>
331</body>
332</html>
333