From 842cf85d4b2a05803f110c501a101af7689b7bee Mon Sep 17 00:00:00 2001
From: Daniel James Copyright © 2002-2005 Joel
de Guzman, David Abrahams
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt )
@@ -42,8 +42,8 @@
Table of Contents
@@ -121,14 +121,10 @@
That's it. We're done. We can now build this as a shared library. The resulting
DLL is now visible to Python. Here's a sample Python session:
-
-
Next stop... Building your Hello World module
from start to finish...
@@ -136,7 +132,7 @@
Last revised: July 01, 2010 at 21:56:58 GMT Last revised: December 26, 2011 at 21:51:27 GMT
@@ -81,8 +81,8 @@ exe embedded_program # name of the executable
<library-path>$(PYTHON_LIB_PATH)
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
-
@@ -95,8 +95,7 @@ exe embedded_program # name of the executable
@@ -152,8 +151,7 @@ exe embedded_program # name of the executable
The
Boost.python provides a function to import a module:
@@ -165,8 +163,8 @@ exe embedded_program # name of the executable
first), and returns it.
- Let's import the
@@ -197,16 +195,16 @@ exe embedded_program # name of the executable
int five_squared = extract<int>(main_namespace["result"]);
- Here we create a dictionary object for the
@@ -216,13 +214,13 @@ exe embedded_program # name of the executable
The
All C++ exceptions must be caught at the boundary with Python code. This boundary
is the point where C++ meets Python. Boost.Python provides a default exception
diff --git a/doc/tutorial/doc/html/python/exposing.html b/doc/tutorial/doc/html/python/exposing.html
index 82eb649b..5547b2f2 100644
--- a/doc/tutorial/doc/html/python/exposing.html
+++ b/doc/tutorial/doc/html/python/exposing.html
@@ -3,7 +3,7 @@
-
-
We can expose additional constructors by passing more
- This actually adds an
-
-
And at last, in Python:
-
Take note that the class property
-
-
+
+
Hello World
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
-
-
+
diff --git a/doc/tutorial/doc/html/python/embedding.html b/doc/tutorial/doc/html/python/embedding.html
index 5a590628..4e1c2185 100644
--- a/doc/tutorial/doc/html/python/embedding.html
+++ b/doc/tutorial/doc/html/python/embedding.html
@@ -3,7 +3,7 @@
-
-
+
+
Building embedded programs
-
+
+
Getting started
_main_
- module.
+ to start the interpreter and create the __main__ module.
-
+
+
Running Python code
globals and locals parameters are
Python dictionaries containing the globals and locals of the context in which
to run the code. For most intents and purposes you can use the namespace
- dictionary of the _main_
- module for both parameters.
+ dictionary of the __main__ module for both parameters.
_main_
- module and run some Python code in its namespace:
+ Let's import the __main__ module and run some Python code
+ in its namespace:
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
@@ -180,8 +178,8 @@ exe embedded_program # name of the executable
This should create a file called 'hello.txt' in the current directory containing
a phrase that is well-known in programming circles.
-
-
+
+
Manipulating Python objects
_main_
- module's namespace. Then we assign 5 squared to the result variable and read
- this variable from the dictionary. Another way to achieve the same result
- is to use eval instead, which returns the result directly:
+ Here we create a dictionary object for the __main__ module's
+ namespace. Then we assign 5 squared to the result variable and read this
+ variable from the dictionary. Another way to achieve the same result is to
+ use eval instead, which returns the result directly:
object result = eval("5 ** 2");
int five_squared = extract<int>(result);
-
-
+
+
Exception handling
try
{
object result = eval("5/0");
- // execution will never get here:
- int five_divided_by_zero = extract<int>(result);
+ // execution will never get here:
+ int five_divided_by_zero = extract<int>(result);
}
catch(error_already_set const &)
{
- // handle the exception in some way
-}
+ // handle the exception in some way
+}
error_already_set exception class doesn't carry any
@@ -238,12 +236,12 @@ exe embedded_program # name of the executable
{
if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
{
- // handle ZeroDivisionError specially
- }
+ // handle ZeroDivisionError specially
+ }
else
{
- // print all other errors to stderr
- PyErr_Print();
+ // print all other errors to stderr
+ PyErr_Print();
}
}
diff --git a/doc/tutorial/doc/html/python/exception.html b/doc/tutorial/doc/html/python/exception.html
index bf5953f3..7c053a7e 100644
--- a/doc/tutorial/doc/html/python/exception.html
+++ b/doc/tutorial/doc/html/python/exception.html
@@ -3,7 +3,7 @@
World in Python. Here's a sample Python
session:
->>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
@@ -90,12 +88,10 @@
We may wish to wrap a class with a non-default constructor. Let us build
on our previous example:
-
struct World
{
- World(std::string msg): msg(msg) {} // added constructor
- void set(std::string msg) { this->msg = msg; }
+ World(std::string msg): msg(msg) {} // added constructor
+ void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
@@ -120,7 +116,7 @@
init<std::string>() exposes the constructor taking
in a std::string (in Python, constructors are spelled
- ""_init_"").
+ ""__init__"").
init<...>s
@@ -140,8 +136,8 @@
class_<Abstract>("Abstract", no_init)
_init_
- method which always raises a Python RuntimeError exception.
+ This actually adds an __init__ method which always raises
+ a Python RuntimeError exception.
>>> x = hello.Var('pi')
>>> x.value = 3.14
>>> print x.name, 'is around', x.value
@@ -183,8 +177,8 @@
Note that
name is exposed as read-only
while value is exposed as read-write.
->>> x.name = 'e' # can't change name
-Traceback (most recent call last):
+
>>> x.name = 'e' # can't change name
+Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: can't set attribute
@@ -198,8 +192,6 @@
The only way to access the class' data is through access (getter/setter)
functions. Access functions expose class properties. Here's an example:
-struct Num
{
Num();
@@ -221,21 +213,17 @@
>>> x = Num()
>>> x.value = 3.14
>>> x.value, x.rovalue
(3.14, 3.14)
->>> x.rovalue = 2.17 # error!
-
+>>> x.rovalue = 2.17 # error!
+rovalue is exposed as
read-only since the rovalue
setter member function is not passed in:
.add_property("rovalue", &Num::get)
// Tell Python to take ownership of factory's result -def("factory", factory, +// Tell Python to take ownership of factory's result +def("factory", factory, return_value_policy<manage_new_object>());@@ -356,7 +344,7 @@ the job of wrapping classes that are meant to overridden in Python, easier. ++ From Start To Finish
@@ -91,8 +91,8 @@ in the command line. Pre-built Boost.Jam executables are available for most platforms. The complete list of Bjam executables can be found here.
-- +
+ Let's Jam!
@@ -107,8 +107,8 @@ The comments contained in the Jamrules file above should be sufficient to get you going.
-- +
+ Running bjam
@@ -133,12 +133,12 @@ using msvc : 8.0 ; # Python configuration -using python : 2.4 : C:/dev/toolsPython ; +using python : 2.4 : C:dev/tools/Python ;
The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools.
The second rule provides information on Python, its version and where it is
- located. The above assumes that the Python installation is in C:/dev/tools/Python/.
+ located. The above assumes that the Python installation is in C:dev/tools\/Python.
If you have one fairly "standard" python installation for your platform,
you might not need to do this.
Creating library path-to-boost_python.dll - Creating library path-to-'''hello_ext'''.exp + Creating library /path-to-hello_ext.exp/ **passed** ... hello.test ...updated 35 targets...diff --git a/doc/tutorial/doc/html/python/iterators.html b/doc/tutorial/doc/html/python/iterators.html index 3f87ab77..9fb402b6 100644 --- a/doc/tutorial/doc/html/python/iterators.html +++ b/doc/tutorial/doc/html/python/iterators.html @@ -3,7 +3,7 @@
for y
in x... is as follows:
--
-iter = x.__iter__() # get iterator -try: +iter = x.__iter__() # get iterator +try: while 1: - y = iter.next() # get each item - ... # process y -except StopIteration: pass # iterator exhausted -+ y = iter.next() # get each item + ... # process y +except StopIteration: pass # iterator exhausted +
Boost.Python provides some mechanisms to make C++ iterators play along nicely
as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that
is compatible with the Python iteration protocol. For example:
-
object get_iterator = iterator<vector<int> >(); object iter = get_iterator(v); object first = iter.next(); @@ -129,8 +125,6 @@ Let's put this into action... Here's an example from some hypothetical bogon Particle accelerator code: --
f = Field() for x in f.pions: smash(x) @@ -140,8 +134,6 @@Now, our C++ Wrapper:
--
class_<F>("Field") .property("pions", range(&F::p_begin, &F::p_end)) .property("bogons", range(&F::b_begin, &F::b_end)); @@ -156,27 +148,23 @@ a Python iterator look like an STL iterator. For that, we usestl_input_iterator<>. Consider how we might implement a function that exposesstd::list<int>::assign()to Python: --
template<typename T> void list_assign(std::list<T>& l, object o) { - // Turn a Python sequence into an STL input range - stl_input_iterator<T> begin(o), end; + // Turn a Python sequence into an STL input range + stl_input_iterator<T> begin(o), end; l.assign(begin, end); } -// Part of the wrapper for list<int> -class_<std::list<int> >("list_int") +// Part of the wrapper for list<int> +class_<std::list<int> >("list_int") .def("assign", &list_assign<int>) - // ... - ; + // ... + ;Now in Python, we can assign any integer sequence to
-list_intobjects:-
x = list_int(); x.assign([1,2,3,4,5])diff --git a/doc/tutorial/doc/html/python/object.html b/doc/tutorial/doc/html/python/object.html index d1cc7138..e05c47ec 100644 --- a/doc/tutorial/doc/html/python/object.html +++ b/doc/tutorial/doc/html/python/object.html @@ -3,7 +3,7 @@Object Interface - + @@ -24,7 +24,7 @@
- Basic Interface
- Derived Object types
@@ -60,8 +60,6 @@To illustrate, this Python code snippet:
--
def f(x, y): if (y == 'foo'): x[3:7] = 'bar' @@ -75,8 +73,6 @@Can be rewritten in C++ using Boost.Python facilities this way:
--
object f(object x, object y) { if (y == "foo") x.slice(3,7) = "bar"; @@ -147,9 +143,9 @@void f(str name) { - object n2 = name.attr("upper")(); // NAME = name.upper() - str NAME = name.upper(); // better - object msg = "%s is bigger than %s" % make_tuple(NAME,name); + object n2 = name.attr("upper")(); // NAME = name.upper() + str NAME = name.upper(); // better + object msg = "%s is bigger than %s" % make_tuple(NAME,name); }@@ -169,7 +165,7 @@ do that in std C++.
@@ -299,8 +295,6 @@
You can access those values in Python as
--
>>> my_module.choice.red my_module.choice.red@@ -308,15 +302,13 @@ where my_module is the module where the enum is declared. You can also create a new scope around a class: --
scope in_X = class_<X>("X") .def( ... ) .def( ... ) ; -// Expose X::nested as X.nested -enum_<X::nested>("nested") +// Expose X::nested as X.nested +enum_<X::nested>("nested") .value("red", red) .value("blue", blue) ; diff --git a/doc/tutorial/doc/html/python/techniques.html b/doc/tutorial/doc/html/python/techniques.html index 0764fcd4..34cfc444 100644 --- a/doc/tutorial/doc/html/python/techniques.html +++ b/doc/tutorial/doc/html/python/techniques.html @@ -3,7 +3,7 @@General Techniques - + @@ -23,7 +23,7 @@
- Creating Packages
- Extending Wrapped Objects in Python
@@ -62,8 +62,8 @@ him to write code like this:import sounds.filters -sounds.filters.echo(...) # echo is a C++ function -+sounds.filters.echo(...) # echo is a C++ function +The first step is to write the wrapping code. We have to export each module separately with Boost.Python, like this: @@ -124,8 +124,6 @@ into his PYTHONPATH and fire up the interpreter:
--
>>> import sounds.io >>> import sounds.filters >>> sound = sounds.io.open('file.mp3') @@ -146,8 +144,6 @@ If we want this flexibility, we will have to complicate our package hierarchy a little. First, we will have to change the name of the extension modules: --
/* file core.cpp */ BOOST_PYTHON_MODULE(_core) { @@ -178,8 +174,6 @@ to each one. But if we leave it that way, the user will have to access the functions in the core module with this syntax: --
>>> import sounds.core._core >>> sounds.core._core.foo(...)@@ -188,7 +182,7 @@ magic: everything that is brought to the__init__.pynamespace can be accessed directly by the user. So, all we have to do is bring the entire namespace from_core.pydtocore/__init__.py. - So add this line of code tosoundscore__init__.py: + So add this line of code tosounds/core/__init__.py:from _core import *@@ -216,7 +210,7 @@ return s- Next, we add this line to
soundsfilters__init__.py: + Next, we add this line tosounds/filters/__init__.py:from echo_noise import echo_noise@@ -237,11 +231,11 @@>>> class C(object): pass >>> ->>> # a regular function ->>> def C_str(self): return 'A C instance!' +>>> # a regular function +>>> def C_str(self): return 'A C instance!' >>> ->>> # now we turn it in a member function ->>> C.__str__ = C_str +>>> # now we turn it in a member function +>>> C.__str__ = C_str >>> >>> c = C() >>> print c @@ -256,8 +250,6 @@ We can do the same with classes that were wrapped with Boost.Python. Suppose we have a classpointin C++: --
class point {...}; BOOST_PYTHON_MODULE(_geom) @@ -269,16 +261,14 @@ If we are using the technique from the previous session, Creating Packages, we can code directly intogeom/__init__.py: --
from _geom import * -# a regular function -def point_str(self): +# a regular function +def point_str(self): return str((self.x, self.y)) -# now we turn it into a member function -point.__str__ = point_str +# now we turn it into a member function +point.__str__ = point_strAll point instances created from C++ will @@ -303,9 +293,9 @@ You can even add a little syntactic sugar with the use of metaclasses. Let's create a special metaclass that "injects" methods in other classes.
-# The one Boost.Python uses for all wrapped classes. -# You can use here any class exported by Boost instead of "point" -BoostPythonMetaclass = point.__class__ +# The one Boost.Python uses for all wrapped classes. +# You can use here any class exported by Boost instead of "point" +BoostPythonMetaclass = point.__class__ class injector(object): class __metaclass__(BoostPythonMetaclass): @@ -316,8 +306,8 @@ setattr(b,k,v) return type.__init__(self, name, bases, dict) -# inject some methods in the point foo -class more_point(injector, point): +# inject some methods in the point foo +class more_point(injector, point): def __repr__(self): return 'Point(x=%s, y=%s)' % (self.x, self.y) def foo(self): @@ -355,8 +345,6 @@ can easily become too high. If this is causing you problems, you can split the class_ definitions in multiple files: --
/* file point.cpp */ #include <point.h> #include <boost/python.hpp>