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">-></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"><</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">></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"><</span><span class="identifier">World</span><span class="special">>(</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">&</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">&</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">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span> 68<span class="special">>>></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">>>></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">>>></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">>>></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">-></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_<World></code> about the constructor 101 we want to expose instead. 102 </p> 103<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</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">></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</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">&</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">&</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<std::string>()</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<...></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"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</span> 125 <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>())</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">&</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">&</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"><</span><span class="identifier">Abstract</span><span class="special">>(</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"><</span><span class="identifier">Var</span><span class="special">>(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</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">&</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">&</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">>>></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">>>></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">>>></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">>>></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">"<stdin>"</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"><</span><span class="identifier">Num</span><span class="special">>(</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">&</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">&</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span> <span class="special">&</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">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span> 217<span class="special">>>></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">>>></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">>>></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">&</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"><</span><span class="identifier">Base</span><span class="special">>(</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"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</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<manage_new_object></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"><</span><span class="identifier">manage_new_object</span><span class="special">>());</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"><</span><span class="identifier">Base</span><span class="special">></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">-></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"><</span><span class="identifier">Base</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></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"><</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">>(</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">(&</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"><</span><span class="identifier">Base</span><span class="special">></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">-></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">-></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"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</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"><</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">>(</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">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&</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">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&</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">>>></span> <span class="identifier">base</span> <span class="special">=</span> <span class="identifier">Base</span><span class="special">()</span> 476<span class="special">>>></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">>>></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">>>></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">>>></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">&</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> 521<span class="identifier">FilePos</span><span class="special">&</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> 522<span class="keyword">bool</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> 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"><</span><span class="identifier">FilePos</span><span class="special">>(</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"><</span><span class="keyword">int</span><span class="special">>())</span> 535 <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">// __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<T>()</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">&</span> <span class="keyword">operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span> 564 565<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</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"><</span><span class="identifier">Rational</span><span class="special">>))</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"><<</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"><<</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</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