• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Exposing Classes</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 Tutorial">
8<link rel="up" href="../index.html" title="Boost.Python Tutorial">
9<link rel="prev" href="hello.html" title="Building Hello World">
10<link rel="next" href="functions.html" title="Functions">
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="hello.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="functions.html"><img src="../../images/next.png" alt="Next"></a>
17</div>
18<div class="section">
19<div class="titlepage"><div><div><h2 class="title" style="clear: both">
20<a name="tutorial.exposing"></a><a class="link" href="exposing.html" title="Exposing Classes">Exposing Classes</a>
21</h2></div></div></div>
22<div class="toc"><dl class="toc">
23<dt><span class="section"><a href="exposing.html#tutorial.exposing.constructors">Constructors</a></span></dt>
24<dt><span class="section"><a href="exposing.html#tutorial.exposing.class_data_members">Class Data Members</a></span></dt>
25<dt><span class="section"><a href="exposing.html#tutorial.exposing.class_properties">Class Properties</a></span></dt>
26<dt><span class="section"><a href="exposing.html#tutorial.exposing.inheritance">Inheritance</a></span></dt>
27<dt><span class="section"><a href="exposing.html#tutorial.exposing.class_virtual_functions">Class Virtual
28      Functions</a></span></dt>
29<dt><span class="section"><a href="exposing.html#tutorial.exposing.virtual_functions_with_default_i">Virtual
30      Functions with Default Implementations</a></span></dt>
31<dt><span class="section"><a href="exposing.html#tutorial.exposing.class_operators_special_function">Class
32      Operators/Special Functions</a></span></dt>
33</dl></div>
34<p>
35      Now let's expose a C++ class to Python.
36    </p>
37<p>
38      Consider a C++ class/struct that we want to expose to Python:
39    </p>
40<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span>
41<span class="special">{</span>
42    <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
43    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
44    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
45<span class="special">};</span>
46</pre>
47<p>
48      We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:
49    </p>
50<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
51<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
52
53<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
54<span class="special">{</span>
55    <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">)</span>
56        <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
57        <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
58    <span class="special">;</span>
59<span class="special">}</span>
60</pre>
61<p>
62      Here, we wrote a C++ class wrapper that exposes the member functions <code class="literal">greet</code>
63      and <code class="literal">set</code>. Now, after building our module as a shared library,
64      we may use our class <code class="literal">World</code> in Python. Here's a sample Python
65      session:
66    </p>
67<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="keyword">import</span> <span class="identifier">hello</span>
68<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
69<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span>
70<span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
71<span class="string">'howdy'</span>
72</pre>
73<div class="section">
74<div class="titlepage"><div><div><h3 class="title">
75<a name="tutorial.exposing.constructors"></a><a class="link" href="exposing.html#tutorial.exposing.constructors" title="Constructors">Constructors</a>
76</h3></div></div></div>
77<p>
78        Our previous example didn't have any explicit constructors. Since <code class="literal">World</code>
79        is declared as a plain struct, it has an implicit default constructor. Boost.Python
80        exposes the default constructor by default, which is why we were able to
81        write
82      </p>
83<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
84</pre>
85<p>
86        We may wish to wrap a class with a non-default constructor. Let us build
87        on our previous example:
88      </p>
89<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">World</span>
90<span class="special">{</span>
91    <span class="identifier">World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">):</span> <span class="identifier">msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span> <span class="special">{}</span> <span class="comment">// added constructor</span>
92    <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
93    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
94    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
95<span class="special">};</span>
96</pre>
97<p>
98        This time <code class="literal">World</code> has no default constructor; our previous
99        wrapping code would fail to compile when the library tried to expose it.
100        We have to tell <code class="literal">class_&lt;World&gt;</code> about the constructor
101        we want to expose instead.
102      </p>
103<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
104<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
105
106<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
107<span class="special">{</span>
108    <span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
109        <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
110        <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
111    <span class="special">;</span>
112<span class="special">}</span>
113</pre>
114<p>
115        <code class="literal">init&lt;std::string&gt;()</code> exposes the constructor taking
116        in a <code class="literal">std::string</code> (in Python, constructors are spelled
117        "<code class="literal">"__init__"</code>").
118      </p>
119<p>
120        We can expose additional constructors by passing more <code class="literal">init&lt;...&gt;</code>s
121        to the <code class="literal">def()</code> member function. Say for example we have
122        another World constructor taking in two doubles:
123      </p>
124<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">World</span><span class="special">&gt;(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
125    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">&gt;())</span>
126    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
127    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
128<span class="special">;</span>
129</pre>
130<p>
131        On the other hand, if we do not wish to expose any constructors at all, we
132        may use <code class="literal">no_init</code> instead:
133      </p>
134<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Abstract</span><span class="special">&gt;(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
135</pre>
136<p>
137        This actually adds an <code class="literal">__init__</code> method which always raises
138        a Python RuntimeError exception.
139      </p>
140</div>
141<div class="section">
142<div class="titlepage"><div><div><h3 class="title">
143<a name="tutorial.exposing.class_data_members"></a><a class="link" href="exposing.html#tutorial.exposing.class_data_members" title="Class Data Members">Class Data Members</a>
144</h3></div></div></div>
145<p>
146        Data members may also be exposed to Python so that they can be accessed as
147        attributes of the corresponding Python class. Each data member that we wish
148        to be exposed may be regarded as <span class="bold"><strong>read-only</strong></span>
149        or <span class="bold"><strong>read-write</strong></span>. Consider this class <code class="literal">Var</code>:
150      </p>
151<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Var</span>
152<span class="special">{</span>
153    <span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span>
154    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span>
155    <span class="keyword">float</span> <span class="identifier">value</span><span class="special">;</span>
156<span class="special">};</span>
157</pre>
158<p>
159        Our C++ <code class="literal">Var</code> class and its data members can be exposed
160        to Python:
161      </p>
162<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Var</span><span class="special">&gt;(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;())</span>
163    <span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span>
164    <span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span>
165</pre>
166<p>
167        Then, in Python, assuming we have placed our Var class inside the namespace
168        hello as we did before:
169      </p>
170<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span>
171<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
172<span class="special">&gt;&gt;&gt;</span> <span class="keyword">print</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span> <span class="string">'is around'</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span>
173<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
174</pre>
175<p>
176        Note that <code class="literal">name</code> is exposed as <span class="bold"><strong>read-only</strong></span>
177        while <code class="literal">value</code> is exposed as <span class="bold"><strong>read-write</strong></span>.
178      </p>
179<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name</span>
180<span class="identifier">Traceback</span> <span class="special">(</span><span class="identifier">most</span> <span class="identifier">recent</span> <span class="identifier">call</span> <span class="identifier">last</span><span class="special">):</span>
181  <span class="identifier">File</span> <span class="string">"&lt;stdin&gt;"</span><span class="special">,</span> <span class="identifier">line</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">in</span> <span class="error">?</span>
182<span class="identifier">AttributeError</span><span class="special">:</span> <span class="identifier">can</span><span class="error">'</span><span class="identifier">t</span> <span class="identifier">set</span> <span class="identifier">attribute</span>
183</pre>
184</div>
185<div class="section">
186<div class="titlepage"><div><div><h3 class="title">
187<a name="tutorial.exposing.class_properties"></a><a class="link" href="exposing.html#tutorial.exposing.class_properties" title="Class Properties">Class Properties</a>
188</h3></div></div></div>
189<p>
190        In C++, classes with public data members are usually frowned upon. Well designed
191        classes that take advantage of encapsulation hide the class' data members.
192        The only way to access the class' data is through access (getter/setter)
193        functions. Access functions expose class properties. Here's an example:
194      </p>
195<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Num</span>
196<span class="special">{</span>
197    <span class="identifier">Num</span><span class="special">();</span>
198    <span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
199    <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">value</span><span class="special">);</span>
200    <span class="special">...</span>
201<span class="special">};</span>
202</pre>
203<p>
204        However, in Python attribute access is fine; it doesn't neccessarily break
205        encapsulation to let users handle attributes directly, because the attributes
206        can just be a different syntax for a method call. Wrapping our <code class="literal">Num</code>
207        class using Boost.Python:
208      </p>
209<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Num</span><span class="special">&gt;(</span><span class="string">"Num"</span><span class="special">)</span>
210    <span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
211    <span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span>
212</pre>
213<p>
214        And at last, in Python:
215      </p>
216<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span>
217<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
218<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span>
219<span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">3.14</span><span class="special">)</span>
220<span class="special">&gt;&gt;&gt;</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!</span>
221</pre>
222<p>
223        Take note that the class property <code class="literal">rovalue</code> is exposed as
224        <span class="bold"><strong>read-only</strong></span> since the <code class="literal">rovalue</code>
225        setter member function is not passed in:
226      </p>
227<pre class="programlisting"><span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
228</pre>
229</div>
230<div class="section">
231<div class="titlepage"><div><div><h3 class="title">
232<a name="tutorial.exposing.inheritance"></a><a class="link" href="exposing.html#tutorial.exposing.inheritance" title="Inheritance">Inheritance</a>
233</h3></div></div></div>
234<p>
235        In the previous examples, we dealt with classes that are not polymorphic.
236        This is not often the case. Much of the time, we will be wrapping polymorphic
237        classes and class hierarchies related by inheritance. We will often have
238        to write Boost.Python wrappers for classes that are derived from abstract
239        base classes.
240      </p>
241<p>
242        Consider this trivial inheritance structure:
243      </p>
244<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span>
245<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
246</pre>
247<p>
248        And a set of C++ functions operating on <code class="literal">Base</code> and <code class="literal">Derived</code>
249        object instances:
250      </p>
251<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span>
252<span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span>
253<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
254</pre>
255<p>
256        We've seen how we can wrap the base class <code class="literal">Base</code>:
257      </p>
258<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
259    <span class="comment">/*...*/</span>
260    <span class="special">;</span>
261</pre>
262<p>
263        Now we can inform Boost.Python of the inheritance relationship between <code class="literal">Derived</code>
264        and its base class <code class="literal">Base</code>. Thus:
265      </p>
266<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"Derived"</span><span class="special">)</span>
267    <span class="comment">/*...*/</span>
268    <span class="special">;</span>
269</pre>
270<p>
271        Doing so, we get some things for free:
272      </p>
273<div class="orderedlist"><ol class="orderedlist" type="1">
274<li class="listitem">
275            Derived automatically inherits all of Base's Python methods (wrapped
276            C++ member functions)
277          </li>
278<li class="listitem">
279            <span class="bold"><strong>If</strong></span> Base is polymorphic, <code class="literal">Derived</code>
280            objects which have been passed to Python via a pointer or reference to
281            <code class="literal">Base</code> can be passed where a pointer or reference to
282            <code class="literal">Derived</code> is expected.
283          </li>
284</ol></div>
285<p>
286        Now, we will expose the C++ free functions <code class="literal">b</code> and <code class="literal">d</code>
287        and <code class="literal">factory</code>:
288      </p>
289<pre class="programlisting"><span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
290<span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
291<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
292</pre>
293<p>
294        Note that free function <code class="literal">factory</code> is being used to generate
295        new instances of class <code class="literal">Derived</code>. In such cases, we use
296        <code class="literal">return_value_policy&lt;manage_new_object&gt;</code> to instruct
297        Python to adopt the pointer to <code class="literal">Base</code> and hold the instance
298        in a new Python <code class="literal">Base</code> object until the the Python object
299        is destroyed. We will see more of Boost.Python <a class="link" href="functions.html#tutorial.functions.call_policies" title="Call Policies">call
300        policies</a> later.
301      </p>
302<pre class="programlisting"><span class="comment">// Tell Python to take ownership of factory's result</span>
303<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span>
304    <span class="identifier">return_value_policy</span><span class="special">&lt;</span><span class="identifier">manage_new_object</span><span class="special">&gt;());</span>
305</pre>
306</div>
307<div class="section">
308<div class="titlepage"><div><div><h3 class="title">
309<a name="tutorial.exposing.class_virtual_functions"></a><a class="link" href="exposing.html#tutorial.exposing.class_virtual_functions" title="Class Virtual Functions">Class Virtual
310      Functions</a>
311</h3></div></div></div>
312<p>
313        In this section, we will learn how to make functions behave polymorphically
314        through virtual functions. Continuing our example, let us add a virtual function
315        to our <code class="literal">Base</code> class:
316      </p>
317<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
318<span class="special">{</span>
319    <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
320    <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
321<span class="special">};</span>
322</pre>
323<p>
324        One of the goals of Boost.Python is to be minimally intrusive on an existing
325        C++ design. In principle, it should be possible to expose the interface for
326        a 3rd party library without changing it. It is not ideal to add anything
327        to our class <code class="computeroutput"><span class="identifier">Base</span></code>. Yet, when
328        you have a virtual function that's going to be overridden in Python and called
329        polymorphically <span class="bold"><strong>from C++</strong></span>, we'll need to
330        add some scaffoldings to make things work properly. What we'll do is write
331        a class wrapper that derives from <code class="computeroutput"><span class="identifier">Base</span></code>
332        that will unintrusively hook into the virtual functions so that a Python
333        override may be called:
334      </p>
335<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
336<span class="special">{</span>
337    <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
338    <span class="special">{</span>
339        <span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span>
340    <span class="special">}</span>
341<span class="special">};</span>
342</pre>
343<p>
344        Notice too that in addition to inheriting from <code class="computeroutput"><span class="identifier">Base</span></code>,
345        we also multiply- inherited <code class="computeroutput"><span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span></code> (See <a href="../../reference/high_level_components/boost_python_wrapper_hpp.html#high_level_components.boost_python_wrapper_hpp.class_template_wrapper" target="_top">Wrapper</a>).
346        The <code class="computeroutput"><span class="identifier">wrapper</span></code> template makes
347        the job of wrapping classes that are meant to overridden in Python, easier.
348      </p>
349<div class="blurb">
350<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
351<p>
352        <span class="inlinemediaobject"><img src="../../images/alert.png"></span>
353        <span class="bold"><strong>MSVC6/7 Workaround</strong></span>
354      </p>
355<p>
356        If you are using Microsoft Visual C++ 6 or 7, you have to write <code class="computeroutput"><span class="identifier">f</span></code> as:
357      </p>
358<p>
359        <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></code>.
360      </p>
361</div>
362<p>
363        BaseWrap's overridden virtual member function <code class="computeroutput"><span class="identifier">f</span></code>
364        in effect calls the corresponding method of the Python object through <code class="computeroutput"><span class="identifier">get_override</span></code>.
365      </p>
366<p>
367        Finally, exposing <code class="computeroutput"><span class="identifier">Base</span></code>:
368      </p>
369<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
370    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span>
371    <span class="special">;</span>
372</pre>
373<p>
374        <code class="computeroutput"><span class="identifier">pure_virtual</span></code> signals Boost.Python
375        that the function <code class="computeroutput"><span class="identifier">f</span></code> is a
376        pure virtual function.
377      </p>
378<div class="note"><table border="0" summary="Note">
379<tr>
380<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
381<th align="left">Note</th>
382</tr>
383<tr><td align="left" valign="top">
384<p>
385          <span class="bold"><strong>member function and methods</strong></span>
386        </p>
387<p>
388          Python, like many object oriented languages uses the term <span class="bold"><strong>methods</strong></span>.
389          Methods correspond roughly to C++'s <span class="bold"><strong>member functions</strong></span>
390        </p>
391</td></tr>
392</table></div>
393</div>
394<div class="section">
395<div class="titlepage"><div><div><h3 class="title">
396<a name="tutorial.exposing.virtual_functions_with_default_i"></a><a class="link" href="exposing.html#tutorial.exposing.virtual_functions_with_default_i" title="Virtual Functions with Default Implementations">Virtual
397      Functions with Default Implementations</a>
398</h3></div></div></div>
399<p>
400        We've seen in the previous section how classes with pure virtual functions
401        are wrapped using Boost.Python's <a href="../../reference/high_level_components/boost_python_wrapper_hpp.html#high_level_components.boost_python_wrapper_hpp.class_template_wrapper" target="_top">class
402        wrapper</a> facilities. If we wish to wrap <span class="bold"><strong>non</strong></span>-pure-virtual
403        functions instead, the mechanism is a bit different.
404      </p>
405<p>
406        Recall that in the <a class="link" href="exposing.html#tutorial.exposing.class_virtual_functions" title="Class Virtual Functions">previous
407        section</a>, we wrapped a class with a pure virtual function that we then
408        implemented in C++, or Python classes derived from it. Our base class:
409      </p>
410<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
411<span class="special">{</span>
412    <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
413<span class="special">};</span>
414</pre>
415<p>
416        had a pure virtual function <code class="literal">f</code>. If, however, its member
417        function <code class="literal">f</code> was not declared as pure virtual:
418      </p>
419<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Base</span>
420<span class="special">{</span>
421    <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
422    <span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span>
423<span class="special">};</span>
424</pre>
425<p>
426        We wrap it this way:
427      </p>
428<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special">&lt;</span><span class="identifier">Base</span><span class="special">&gt;</span>
429<span class="special">{</span>
430    <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
431    <span class="special">{</span>
432        <span class="keyword">if</span> <span class="special">(</span><span class="identifier">override</span> <span class="identifier">f</span> <span class="special">=</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span>
433            <span class="keyword">return</span> <span class="identifier">f</span><span class="special">();</span> <span class="comment">// *note*</span>
434        <span class="keyword">return</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span>
435    <span class="special">}</span>
436
437    <span class="keyword">int</span> <span class="identifier">default_f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span> <span class="special">}</span>
438<span class="special">};</span>
439</pre>
440<p>
441        Notice how we implemented <code class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></code>. Now,
442        we have to check if there is an override for <code class="computeroutput"><span class="identifier">f</span></code>.
443        If none, then we call <code class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></code>.
444      </p>
445<div class="blurb">
446<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
447<p>
448        <span class="inlinemediaobject"><img src="../../images/alert.png"></span>
449        <span class="bold"><strong>MSVC6/7 Workaround</strong></span>
450      </p>
451<p>
452        If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
453        with the <code class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></code> as:
454      </p>
455<p>
456        <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special">&lt;</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&gt;(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></code>.
457      </p>
458</div>
459<p>
460        Finally, exposing:
461      </p>
462<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">&gt;(</span><span class="string">"Base"</span><span class="special">)</span>
463    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span>
464    <span class="special">;</span>
465</pre>
466<p>
467        Take note that we expose both <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&amp;</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></code>. Boost.Python needs to keep track
468        of 1) the dispatch function <code class="literal">f</code> and 2) the forwarding function
469        to its default implementation <code class="literal">default_f</code>. There's a special
470        <code class="literal">def</code> function for this purpose.
471      </p>
472<p>
473        In Python, the results would be as expected:
474      </p>
475<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span> <span class="special">=</span> <span class="identifier">Base</span><span class="special">()</span>
476<span class="special">&gt;&gt;&gt;</span> <span class="keyword">class</span> <span class="identifier">Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span>
477<span class="special">...</span>     <span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
478<span class="special">...</span>         <span class="keyword">return</span> <span class="number">42</span>
479<span class="special">...</span>
480<span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
481</pre>
482<p>
483        Calling <code class="literal">base.f()</code>:
484      </p>
485<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
486<span class="number">0</span>
487</pre>
488<p>
489        Calling <code class="literal">derived.f()</code>:
490      </p>
491<pre class="programlisting"><span class="special">&gt;&gt;&gt;</span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
492<span class="number">42</span>
493</pre>
494</div>
495<div class="section">
496<div class="titlepage"><div><div><h3 class="title">
497<a name="tutorial.exposing.class_operators_special_function"></a><a class="link" href="exposing.html#tutorial.exposing.class_operators_special_function" title="Class Operators/Special Functions">Class
498      Operators/Special Functions</a>
499</h3></div></div></div>
500<h3>
501<a name="tutorial.exposing.class_operators_special_function.h0"></a>
502        <span class="phrase"><a name="tutorial.exposing.class_operators_special_function.python_operators"></a></span><a class="link" href="exposing.html#tutorial.exposing.class_operators_special_function.python_operators">Python
503        Operators</a>
504      </h3>
505<p>
506        C is well known for the abundance of operators. C++ extends this to the extremes
507        by allowing operator overloading. Boost.Python takes advantage of this and
508        makes it easy to wrap C++ operator-powered classes.
509      </p>
510<p>
511        Consider a file position class <code class="literal">FilePos</code> and a set of operators
512        that take on FilePos instances:
513      </p>
514<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">FilePos</span> <span class="special">{</span> <span class="comment">/*...*/</span> <span class="special">};</span>
515
516<span class="identifier">FilePos</span>     <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
517<span class="identifier">FilePos</span>     <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
518<span class="keyword">int</span>         <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
519<span class="identifier">FilePos</span>     <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
520<span class="identifier">FilePos</span><span class="special">&amp;</span>    <span class="keyword">operator</span><span class="special">+=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
521<span class="identifier">FilePos</span><span class="special">&amp;</span>    <span class="keyword">operator</span><span class="special">-=(</span><span class="identifier">FilePos</span><span class="special">&amp;,</span> <span class="keyword">int</span><span class="special">);</span>
522<span class="keyword">bool</span>        <span class="keyword">operator</span><span class="special">&lt;(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
523</pre>
524<p>
525        The class and the various operators can be mapped to Python rather easily
526        and intuitively:
527      </p>
528<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">FilePos</span><span class="special">&gt;(</span><span class="string">"FilePos"</span><span class="special">)</span>
529    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span>          <span class="comment">// __add__</span>
530    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span>          <span class="comment">// __radd__</span>
531    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span>           <span class="comment">// __sub__</span>
532    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="keyword">int</span><span class="special">())</span>          <span class="comment">// __sub__</span>
533    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+=</span> <span class="keyword">int</span><span class="special">())</span>         <span class="comment">// __iadd__</span>
534    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-=</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;())</span>
535    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">&lt;</span> <span class="identifier">self</span><span class="special">);</span>          <span class="comment">// __lt__</span>
536</pre>
537<p>
538        The code snippet above is very clear and needs almost no explanation at all.
539        It is virtually the same as the operators' signatures. Just take note that
540        <code class="literal">self</code> refers to FilePos object. Also, not every class
541        <code class="literal">T</code> that you might need to interact with in an operator
542        expression is (cheaply) default-constructible. You can use <code class="literal">other&lt;T&gt;()</code>
543        in place of an actual <code class="literal">T</code> instance when writing "self
544        expressions".
545      </p>
546<h3>
547<a name="tutorial.exposing.class_operators_special_function.h1"></a>
548        <span class="phrase"><a name="tutorial.exposing.class_operators_special_function.special_methods"></a></span><a class="link" href="exposing.html#tutorial.exposing.class_operators_special_function.special_methods">Special
549        Methods</a>
550      </h3>
551<p>
552        Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
553        supports all of the standard special method names supported by real Python
554        class instances. A similar set of intuitive interfaces can also be used to
555        wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>.
556        Example:
557      </p>
558<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">Rational</span>
559<span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">operator</span> <span class="keyword">double</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="special">};</span>
560
561<span class="identifier">Rational</span> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span> <span class="identifier">Rational</span><span class="special">);</span>
562<span class="identifier">Rational</span> <span class="identifier">abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span>
563<span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">ostream</span><span class="special">&amp;,</span><span class="identifier">Rational</span><span class="special">);</span>
564
565<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;(</span><span class="string">"Rational"</span><span class="special">)</span>
566    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span>                  <span class="comment">// __float__</span>
567    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">other</span><span class="special">&lt;</span><span class="identifier">Rational</span><span class="special">&gt;))</span>    <span class="comment">// __pow__</span>
568    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span>                     <span class="comment">// __abs__</span>
569    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span>                     <span class="comment">// __str__</span>
570    <span class="special">;</span>
571</pre>
572<p>
573        Need we say more?
574      </p>
575<div class="note"><table border="0" summary="Note">
576<tr>
577<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../images/note.png"></td>
578<th align="left">Note</th>
579</tr>
580<tr><td align="left" valign="top"><p>
581          What is the business of <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>? Well, the method <code class="computeroutput"><span class="identifier">str</span></code> requires the <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special">&lt;&lt;</span></code>
582          is used by the method defined by <code class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></code>.
583        </p></td></tr>
584</table></div>
585</div>
586</div>
587<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
588<td align="left"></td>
589<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
590      de Guzman, David Abrahams<p>
591        Distributed under the Boost Software License, Version 1.0. (See accompanying
592        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>
593      </p>
594</div></td>
595</tr></table>
596<hr>
597<div class="spirit-nav">
598<a accesskey="p" href="hello.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="functions.html"><img src="../../images/next.png" alt="Next"></a>
599</div>
600</body>
601</html>
602