/
cython_wrapper.html
240 lines (195 loc) · 16.8 KB
/
cython_wrapper.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<!DOCTYPE html>
<html lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>How to wrap QuantLib classes with cython — Quantlib cython wrapper 0.1.1 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=f37d8280" />
<script src="_static/documentation_options.js?v=a58bc63e"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script crossorigin="anonymous" integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="how-to-wrap-quantlib-classes-with-cython">
<h1>How to wrap QuantLib classes with cython<a class="headerlink" href="#how-to-wrap-quantlib-classes-with-cython" title="Link to this heading">¶</a></h1>
<p>These notes provide a step by step guide to wrapping a QuantLib (QL) class
with cython, so that it can be invoked from python.</p>
<p>The objective is to make available in python a set of modules that
exactly mirror the QL class hierarchy. For example, QL provides a
class named <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code>, that represents a simple price
measurement. The C++ class is defined as follows:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">SimpleQuote</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">Quote</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">public</span><span class="o">:</span>
<span class="w"> </span><span class="n">SimpleQuote</span><span class="p">(</span><span class="n">Real</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Null</span><span class="o"><</span><span class="n">Real</span><span class="o">></span><span class="p">());</span>
<span class="w"> </span><span class="n">Real</span><span class="w"> </span><span class="nf">value</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="p">;</span>
<span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">isValid</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="p">;</span>
<span class="w"> </span><span class="n">Real</span><span class="w"> </span><span class="nf">setValue</span><span class="p">(</span><span class="n">Real</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Null</span><span class="o"><</span><span class="n">Real</span><span class="o">></span><span class="p">());</span>
<span class="p">};</span>
</pre></div>
</div>
<p>After wrapping the C++ class, this class is now available in python:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">quantlib.quotes.simplequote</span> <span class="kn">import</span> <span class="n">SimpleQuote</span>
<span class="n">spot</span> <span class="o">=</span> <span class="n">SimpleQuote</span><span class="p">(</span><span class="mf">3.14</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Spot </span><span class="si">%f</span><span class="s1">'</span> <span class="o">%</span> <span class="n">spot</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
</pre></div>
</div>
<p>A couple of observations are worth mentioning:</p>
<ul class="simple">
<li><p>pyql preserves the module hierarchy of QuantLib:
the SimpleQuote class is defined in the <code class="docutils literal notranslate"><span class="pre">quantlib/quotes/simplequote.hpp</span></code> header in C++.</p></li>
<li><p>pyql exposes QuantLib in a pythonic fashion: instead of exposing the accessor value(),
pyql implements the property value.</p></li>
</ul>
<section id="the-interface-code">
<h2>The Interface Code<a class="headerlink" href="#the-interface-code" title="Link to this heading">¶</a></h2>
<p>To expose QL class <code class="docutils literal notranslate"><span class="pre">foo</span></code>, you need to create three files. For the sake of
standardization, they should be named as follows:</p>
<dl class="field-list simple">
<dt class="field-odd">_foo.pxd<span class="colon">:</span></dt>
<dd class="field-odd"><p>A header file to declare the C++ class being exposed,</p>
</dd>
<dt class="field-even">foo.pxd<span class="colon">:</span></dt>
<dd class="field-even"><p>A header file where the corresponding python class is declared</p>
</dd>
<dt class="field-odd">foo.pyx<span class="colon">:</span></dt>
<dd class="field-odd"><p>The implementation of the corresponding python class</p>
</dd>
</dl>
<p>The content of each file is now described in details.</p>
</section>
<section id="declaration-of-the-ql-classes-to-be-exposed">
<h2>Declaration of the QL classes to be exposed<a class="headerlink" href="#declaration-of-the-ql-classes-to-be-exposed" title="Link to this heading">¶</a></h2>
<p>This file contains the declaration of the QL
class being exposed. For example, the header file <code class="docutils literal notranslate"><span class="pre">_simplequote.pxd</span></code> is
as follows:</p>
<div class="highlight-cython notranslate"><div class="highlight"><pre><span></span><span class="k">from</span> <span class="nn">quantlib.types</span> <span class="k">cimport</span> <span class="n">Real</span>
<span class="k">from</span> <span class="nn">quantlib._quote</span> <span class="k">cimport</span> <span class="n">Quote</span>
<span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">'ql/quotes/simplequote.hpp'</span> <span class="n">namespace</span> <span class="s">'QuantLib'</span><span class="p">:</span>
<span class="k">cdef</span> <span class="kt">cppclass</span> <span class="nf">SimpleQuote</span><span class="p">(</span><span class="n">Quote</span><span class="p">):</span>
<span class="n">SimpleQuote</span><span class="p">(</span><span class="n">Real</span> <span class="n">value</span><span class="p">)</span>
<span class="n">Real</span> <span class="n">setValue</span><span class="p">(</span><span class="n">Real</span> <span class="n">value</span><span class="p">)</span>
<span class="n">void</span> <span class="n">reset</span><span class="p">()</span>
</pre></div>
</div>
<p>In this file, we declare the class <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code> qwhich derives from <code class="docutils literal notranslate"><span class="pre">Quote</span></code>.
The syntax is almost identical to the corresponding C++ header file. The
types used in declaring arguments are defined in <code class="docutils literal notranslate"><span class="pre">quantlib.types</span></code>.</p>
</section>
<section id="declaration-of-the-python-class">
<h2>Declaration of the python class<a class="headerlink" href="#declaration-of-the-python-class" title="Link to this heading">¶</a></h2>
<p>The second header file declares the python classes that will be wrapping
the QL classes. The file <code class="docutils literal notranslate"><span class="pre">simplequote.pxd</span></code> is reproduced below:</p>
<div class="highlight-cython notranslate"><div class="highlight"><pre><span></span><span class="k">from</span> <span class="nn">quantlib.quote</span> <span class="k">cimport</span> <span class="n">Quote</span>
<span class="k">cdef</span> <span class="k">class</span> <span class="nf">SimpleQuote</span><span class="p">(</span><span class="n">Quote</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Notice that in our header files we use ‘Quote’ to refer the the C++
class (in file _simplequote.pxd) and to the python class (in file
quote.pxd). To avoid confusion we use the following convention:</p>
<ul class="simple">
<li><p>the C++ class is always referred to as <code class="docutils literal notranslate"><span class="pre">_qt.Quote</span></code>.</p></li>
<li><p>the python class is always referred to as <code class="docutils literal notranslate"><span class="pre">Quote</span></code></p></li>
</ul>
<p>The cython wrapper class holds a reference to the QL C++ class. As we do not
want to do any memory handling on the Python side, we always wrap the C++
object into a shared pointer whose lifetime is tied to the lifetime of the
wrapping class. That way it will get deallocated automatically when the Python
GC runs.</p>
</section>
<section id="implementation-of-the-python-class">
<h2>Implementation of the python class<a class="headerlink" href="#implementation-of-the-python-class" title="Link to this heading">¶</a></h2>
<p>The third file contains the implementation of the cython wrapper
class. As an illustration, the implementation of the <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code>
python class is reproduced below:</p>
<div class="highlight-cython notranslate"><div class="highlight"><pre><span></span><span class="k">cdef</span> <span class="k">class</span> <span class="nf">SimpleQuote</span><span class="p">(</span><span class="n">Quote</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">double</span> <span class="n">value</span><span class="o">=</span><span class="n">QL_NULL_REAL</span><span class="p">):</span>
<span class="w"> </span><span class="sd">""" Market element returning a stored value"""</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span><span class="o">.</span><span class="n">reset</span><span class="p">(</span><span class="n">new</span> <span class="n">_sq</span><span class="o">.</span><span class="n">SimpleQuote</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span><span class="o">.</span><span class="n">get</span><span class="p">()</span><span class="o">.</span><span class="n">isValid</span><span class="p">():</span>
<span class="k">return</span> <span class="s">'Simple Quote: </span><span class="si">%f</span><span class="s">'</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span><span class="o">.</span><span class="n">get</span><span class="p">()</span><span class="o">.</span><span class="n">value</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="s">'Empty Quote'</span>
<span class="k">property</span> <span class="nf">value</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span><span class="o">.</span><span class="n">get</span><span class="p">()</span><span class="o">.</span><span class="n">value</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">__set__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">double</span> <span class="n">value</span><span class="p">):</span>
<span class="p">(</span><span class="o"><</span><span class="n">_qt</span><span class="o">.</span><span class="n">SimpleQuote</span><span class="o">*></span><span class="bp">self</span><span class="o">.</span><span class="n">_thisptr</span><span class="o">.</span><span class="n">get</span><span class="p">())</span><span class="o">.</span><span class="n">setValue</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method invokes the C++ constructor, which returns a shared pointer.</p>
<p>Properties are used to give a more pythonic flavor to the wrapping.
In python, we get the value of the <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code> with the syntax
<code class="docutils literal notranslate"><span class="pre">spot.value</span></code> rather than <code class="docutils literal notranslate"><span class="pre">spot.value()</span></code>, had we exposed
directly the C++ accessor.</p>
<p>Remember from the previous section that <code class="docutils literal notranslate"><span class="pre">_thisptr</span></code> is a shared pointer
on a <code class="docutils literal notranslate"><span class="pre">Quote</span></code>, which is a virtual class. The <code class="docutils literal notranslate"><span class="pre">setValue</span></code>
method is defined in the <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code> concrete class,
and the shared pointer must therefore be cast
into a <code class="docutils literal notranslate"><span class="pre">SimpleQuote</span></code> shared pointer in order to invoke <code class="docutils literal notranslate"><span class="pre">setValue()</span></code>.</p>
</section>
<section id="managing-c-references-using-shared-ptr">
<h2>Managing C++ references using shared_ptr<a class="headerlink" href="#managing-c-references-using-shared-ptr" title="Link to this heading">¶</a></h2>
<p>All the Cython extension references should be declared using shared_ptr.</p>
<p>Every time a shared_ptr reference is received, never assigns the target pointer
to a local pointer variables as it might be deallocated. Always use the copy
constructor of the shared_ptr to get a local copy of it, stack allocated (there
is no need to use new).</p>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="index.html">Quantlib cython wrapper</a></h1>
<h3>Navigation</h3>
<ul>
<li class="toctree-l1"><a class="reference internal" href="getting_started.html">Getting started</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="users_guide.html">User’s guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="reference_guide.html">Reference guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="roadmap.html">Roadmap</a></li>
<li class="toctree-l1"><a class="reference internal" href="roadmap.html#documentation">Documentation</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="index.html">Documentation overview</a><ul>
</ul></li>
</ul>
</div>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©2011, Didrik Pinte, Patrick Henaff.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 7.3.7</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="_sources/cython_wrapper.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>