mirror of
https://github.com/boostorg/python.git
synced 2026-01-26 06:42:27 +00:00
More tweaks (tutorial)
[SVN r15826]
This commit is contained in:
@@ -36,22 +36,26 @@ building Boost.Python, check out: <a href="../../building.html">
|
||||
building.html</a>.
|
||||
After this brief <i>bjam</i> tutorial, we should have built two DLLs:</p>
|
||||
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
|
||||
This assumes of course that we are running on Windows.</p>
|
||||
if you are on Windows, and</p>
|
||||
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
|
||||
if you are on Unix.</p>
|
||||
<p>
|
||||
The tutorial example can be found in the directory:
|
||||
<tt>/libs/python/example/tutorial</tt>. There, you can find:</p>
|
||||
<tt>libs/python/example/tutorial</tt>. There, you can find:</p>
|
||||
<ul><li>hello.cpp</li><li>Jamfile</li></ul><p>
|
||||
The <tt>hello.cpp</tt> file is our C++ hello world example. The <tt>Jamfile</tt> is a
|
||||
minimalist <i>bjam</i> script that builds the DLLs for us.</p>
|
||||
<p>
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory. Pre-built Boost.Jam executables are available for some
|
||||
directory. Pre-built Boost.Jam executables are available for most
|
||||
platforms. For example, a pre-built Microsoft Windows bjam executable can
|
||||
be downloaded <a href="http://boost.sourceforge.net/jam-executables/bin.ntx86/bjam.zip">
|
||||
here</a>.
|
||||
The complete list of bjam pre-built executables can be found <a href="../../../../../tools/build/index.html#Jam">
|
||||
here</a>.</p>
|
||||
<a name="lets_jam_"></a><h2>Lets Jam!</h2><p>
|
||||
<img src="theme/jam.png"></img></p>
|
||||
<p>
|
||||
Here is our minimalist Jamfile:</p>
|
||||
<code><pre>
|
||||
subproject libs/python/example/tutorial ;
|
||||
@@ -99,8 +103,9 @@ Python modules. Example:</p>
|
||||
</span></pre></code>
|
||||
<p>
|
||||
The above assumes that the Python installation is in <tt>c:/dev/tools/python</tt>
|
||||
and that we are using Python version 2.2. Be sure not to include a third
|
||||
number, e.g. <b>not</b> "2.2.1", even if that's the version you have.</p>
|
||||
and that we are using Python version 2.2. You'll have to tweak this path
|
||||
appropriately. <img src="theme/note.gif"></img> Be sure not to include a third number, e.g. <b>not</b> "2.2.1",
|
||||
even if that's the version you have.</p>
|
||||
<p>
|
||||
Now we are ready... Be sure to <tt>cd</tt> to <tt>libs/python/example/tutorial</tt>
|
||||
where the tutorial <tt>"hello.cpp"</tt> and the <tt>"Jamfile"</tt> is situated.</p>
|
||||
@@ -139,6 +144,10 @@ And so on... Finally:</p>
|
||||
</pre></code><p>
|
||||
If all is well, you should now have:</p>
|
||||
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
|
||||
if you are on Windows, and</p>
|
||||
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
|
||||
if you are on Unix.</p>
|
||||
<p>
|
||||
<tt>boost_python.dll</tt> can be found somewhere in <tt>libs\python\build\bin</tt>
|
||||
while <tt>hello.pyd</tt> can be found somewhere in
|
||||
<tt>libs\python\example\tutorial\bin</tt>. After a successful build, you can just
|
||||
|
||||
@@ -142,7 +142,7 @@ or more policies can be composed by chaining. Here's the general syntax:</p>
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found <a href="../../v2/CallPolicies.html">
|
||||
these can be found <a href="../../v2/reference.html#models_of_call_policies">
|
||||
here</a>.</p>
|
||||
<ul><li><b>with_custodian_and_ward</b><br> Ties lifetimes of the arguments</li><li><b>with_custodian_and_ward_postcall</b><br> Ties lifetimes of the arguments and results</li><li><b>return_internal_reference</b><br> Ties lifetime of one argument to that of result</li><li><b>return_value_policy<T> with T one of:</b><br></li><li><b>reference_existing_object</b><br>naïve (dangerous) approach</li><li><b>copy_const_reference</b><br>Boost.Python v1 approach</li><li><b>copy_non_const_reference</b><br></li><li><b>manage_new_object</b><br> Adopt a pointer and hold the instance</li></ul><table width="80%" border="0" align="center">
|
||||
<tr>
|
||||
|
||||
@@ -56,12 +56,11 @@ Then, in Python:</p>
|
||||
Note that <tt>name</tt> is exposed as <b>read-only</b> while <tt>value</tt> is exposed
|
||||
as <b>read-write</b>.</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>name </span><span class=special>= </span><span class=literal>'e' </span>#<span class=identifier>can</span><span class=literal>'t change name
|
||||
>>> x.name = 'e' # can't change name
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: can'</span><span class=identifier>t </span><span class=identifier>set </span><span class=identifier>attribute
|
||||
</span></pre></code>
|
||||
<table border="0">
|
||||
AttributeError: can't set attribute
|
||||
</pre></code><table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="constructors.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
|
||||
@@ -92,15 +92,16 @@ polymorphically <i>from</i> <b>C++</b>. </td>
|
||||
<p>
|
||||
Wrapping <tt>Base</tt> and the free function <tt>call_f</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>, </span><span class=identifier>noncopyable</span><span class=special>>(</span><span class=string>"Base"</span><span class=special>, </span><span class=identifier>no_init</span><span class=special>)
|
||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</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><span class=identifier>no_init</span><span class=special>)
|
||||
</span><span class=special>;
|
||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"call_f"</span><span class=special>, </span><span class=identifier>call_f</span><span class=special>);
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Notice that we parameterized the <tt>class_</tt> template with <tt>BaseWrap</tt> as the
|
||||
second parameter. What is <tt>noncopyable</tt>? Without it, the library will try
|
||||
to instantiate a copy constructor for returning Base objects from
|
||||
functions.</p>
|
||||
to create code for converting Base return values of wrapped functions to
|
||||
Python. To do that, it needs Base's copy constructor... which isn't
|
||||
available, since Base is an abstract class.</p>
|
||||
<p>
|
||||
In Python, let us try to instantiate our <tt>Base</tt> class:</p>
|
||||
<code><pre>
|
||||
|
||||
@@ -64,7 +64,7 @@ expose instead.</p>
|
||||
<p>
|
||||
<tt>init<std::string>()</tt> exposes the constructor taking in a
|
||||
<tt>std::string</tt> (in Python, constructors are spelled
|
||||
"<tt>__init__(...)</tt>").</p>
|
||||
"<tt>"__init__"</tt>").</p>
|
||||
<p>
|
||||
We can expose additional constructors by passing more <tt>init<...></tt>s to
|
||||
the <tt>def()</tt> member function. Say for example we have another World
|
||||
|
||||
@@ -70,18 +70,21 @@ member functions.</p>
|
||||
<p>
|
||||
Demonstrates that you can write the C++ equivalent of <tt>"format" % x,y,z</tt>
|
||||
in Python, which is useful since there's no easy way to do that in std C++.</p>
|
||||
<table width="80%" border="0" align="center">
|
||||
<tr>
|
||||
<td class="note_box">
|
||||
<img src="theme/alert.gif"></img> Beware the common pitfall of
|
||||
forgetting that the constructors of most of Python's mutable types
|
||||
make copies, just as in Python.<br><br>
|
||||
|
||||
<tt>dict d(x.attr("__dict__")); # makes a copy of x's dict<br>
|
||||
d['whatever'] = 3; # modifies a copy of x.__dict__ (not the original)<br></tt>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
<img src="theme/alert.gif"></img> <b>Beware</b> the common pitfall of forgetting that the constructors
|
||||
of most of Python's mutable types make copies, just as in Python.</p>
|
||||
<p>
|
||||
Python:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>dict</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__</span><span class=special>) </span>#<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
|
||||
</span><span class=special>>>> </span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span>#<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
|
||||
</span></pre></code>
|
||||
<p>
|
||||
C++:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>dict </span><span class=identifier>d</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"__dict__"</span><span class=special>)); </span>#<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
|
||||
</span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span><span class=special>= </span><span class=number>3</span><span class=special>; </span>#<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
|
||||
</span></pre></code>
|
||||
<a name="class__lt_t_gt__as_objects"></a><h2>class_<T> as objects</h2><p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt>class_<T></tt> may
|
||||
also be one of these types! The following code snippet wraps the class
|
||||
|
||||
@@ -65,10 +65,15 @@ After this brief ['bjam] tutorial, we should have built two DLLs:
|
||||
* boost_python.dll
|
||||
* hello.pyd
|
||||
|
||||
This assumes of course that we are running on Windows.
|
||||
if you are on Windows, and
|
||||
|
||||
* libboost_python.so
|
||||
* hello.so
|
||||
|
||||
if you are on Unix.
|
||||
|
||||
The tutorial example can be found in the directory:
|
||||
[^/libs/python/example/tutorial]. There, you can find:
|
||||
[^libs/python/example/tutorial]. There, you can find:
|
||||
|
||||
* hello.cpp
|
||||
* Jamfile
|
||||
@@ -77,12 +82,13 @@ The [^hello.cpp] file is our C++ hello world example. The [^Jamfile] is a
|
||||
minimalist ['bjam] script that builds the DLLs for us.
|
||||
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory. Pre-built Boost.Jam executables are available for some
|
||||
directory. Pre-built Boost.Jam executables are available for most
|
||||
platforms. For example, a pre-built Microsoft Windows bjam executable can
|
||||
be downloaded [@http://boost.sourceforge.net/jam-executables/bin.ntx86/bjam.zip here].
|
||||
The complete list of bjam pre-built executables can be found [@../../../../../tools/build/index.html#Jam here].
|
||||
|
||||
[h2 Lets Jam!]
|
||||
[$theme/jam.png]
|
||||
|
||||
Here is our minimalist Jamfile:
|
||||
|
||||
@@ -141,8 +147,9 @@ Python modules. Example:
|
||||
set PYTHON_VERSION=2.2
|
||||
|
||||
The above assumes that the Python installation is in [^c:/dev/tools/python]
|
||||
and that we are using Python version 2.2. Be sure not to include a third
|
||||
number, e.g. [*not] "2.2.1", even if that's the version you have.
|
||||
and that we are using Python version 2.2. You'll have to tweak this path
|
||||
appropriately. __note__ Be sure not to include a third number, e.g. [*not] "2.2.1",
|
||||
even if that's the version you have.
|
||||
|
||||
Now we are ready... Be sure to [^cd] to [^libs/python/example/tutorial]
|
||||
where the tutorial [^"hello.cpp"] and the [^"Jamfile"] is situated.
|
||||
@@ -186,6 +193,13 @@ If all is well, you should now have:
|
||||
* boost_python.dll
|
||||
* hello.pyd
|
||||
|
||||
if you are on Windows, and
|
||||
|
||||
* libboost_python.so
|
||||
* hello.so
|
||||
|
||||
if you are on Unix.
|
||||
|
||||
[^boost_python.dll] can be found somewhere in [^libs\python\build\bin]
|
||||
while [^hello.pyd] can be found somewhere in
|
||||
[^libs\python\example\tutorial\bin]. After a successful build, you can just
|
||||
@@ -276,7 +290,7 @@ expose instead.
|
||||
|
||||
[^init<std::string>()] exposes the constructor taking in a
|
||||
[^std::string] (in Python, constructors are spelled
|
||||
"[^__init__(...)]").
|
||||
"[^"__init__"]").
|
||||
|
||||
We can expose additional constructors by passing more [^init<...>]s to
|
||||
the [^def()] member function. Say for example we have another World
|
||||
@@ -326,10 +340,12 @@ Then, in Python:
|
||||
Note that [^name] is exposed as [*read-only] while [^value] is exposed
|
||||
as [*read-write].
|
||||
|
||||
[pre
|
||||
>>> x.name = 'e' # can't change name
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: can't set attribute
|
||||
]
|
||||
|
||||
[page:1 Class Properties]
|
||||
|
||||
@@ -482,14 +498,15 @@ polymorphically ['from] [*C++].]
|
||||
|
||||
Wrapping [^Base] and the free function [^call_f]:
|
||||
|
||||
class_<Base, BaseWrap, noncopyable>("Base", no_init)
|
||||
class_<Base, BaseWrap, boost::noncopyable>("Base", no_init)
|
||||
;
|
||||
def("call_f", call_f);
|
||||
|
||||
Notice that we parameterized the [^class_] template with [^BaseWrap] as the
|
||||
second parameter. What is [^noncopyable]? Without it, the library will try
|
||||
to instantiate a copy constructor for returning Base objects from
|
||||
functions.
|
||||
to create code for converting Base return values of wrapped functions to
|
||||
Python. To do that, it needs Base's copy constructor... which isn't
|
||||
available, since Base is an abstract class.
|
||||
|
||||
In Python, let us try to instantiate our [^Base] class:
|
||||
|
||||
@@ -820,7 +837,7 @@ or more policies can be composed by chaining. Here's the general syntax:
|
||||
policy3<args...> > >
|
||||
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found [@../../v2/CallPolicies.html here].
|
||||
these can be found [@../../v2/reference.html#models_of_call_policies here].
|
||||
|
||||
* [*with_custodian_and_ward][br] Ties lifetimes of the arguments
|
||||
* [*with_custodian_and_ward_postcall][br] Ties lifetimes of the arguments and results
|
||||
@@ -1007,13 +1024,18 @@ member functions.
|
||||
Demonstrates that you can write the C++ equivalent of [^"format" % x,y,z]
|
||||
in Python, which is useful since there's no easy way to do that in std C++.
|
||||
|
||||
[blurb __alert__ Beware the common pitfall of
|
||||
forgetting that the constructors of most of Python's mutable types
|
||||
make copies, just as in Python.[br][br]
|
||||
__alert__ [*Beware] the common pitfall of forgetting that the constructors
|
||||
of most of Python's mutable types make copies, just as in Python.
|
||||
|
||||
[^dict d(x.attr("__dict__")); # makes a copy of x's dict[br]
|
||||
'''d['whatever']''' = 3; # modifies a copy of x.__dict__ (not the original)[br]]
|
||||
]
|
||||
Python:
|
||||
|
||||
>>> d = dict(x.__dict__) # copies x.__dict__
|
||||
>>> d['whatever'] # modifies the copy
|
||||
|
||||
C++:
|
||||
|
||||
dict d(x.attr("__dict__")); # copies x.__dict__
|
||||
d['whatever'] = 3; # modifies the copy
|
||||
|
||||
[h2 class_<T> as objects]
|
||||
|
||||
|
||||
BIN
doc/tutorial/doc/theme/jam.png
vendored
Normal file
BIN
doc/tutorial/doc/theme/jam.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
Reference in New Issue
Block a user