diff --git a/doc/tutorial/doc/html/index.html b/doc/tutorial/doc/html/index.html index e85d5d3a..d63480c1 100644 --- a/doc/tutorial/doc/html/index.html +++ b/doc/tutorial/doc/html/index.html @@ -1,11 +1,11 @@
- -| More |
Copyright © 2002-2005 Joel +
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 ) @@ -79,7 +79,7 @@
@@ -93,10 +93,10 @@ code takes on the look of a kind of declarative interface definition language (IDL).
-Following C/C++ tradition, let's start with the "hello, world". A C++ Function: @@ -129,23 +129,17 @@
-
--
-- Next stop... Building your Hello World - module from start to finish... -
--
-
+ Next stop... Building your Hello World module + from start to finish... +
Last revised: November 22, 2008 at 03:24:11 GMT |
+Last revised: July 01, 2010 at 21:56:58 GMT |
-To be able to embed python into your programs, you have to link to both Boost.Python's as well as Python's own runtime library.
Boost.Python's library comes in two variants. Both are located in Boost's
- /libs/python/build/bin-stage subdirectory. On Windows, the
- variants are called boost_python.lib (for release builds)
- and boost_python_debug.lib (for debugging). If you can't
+ /libs/python/build/bin-stage subdirectory. On Windows, the
+ variants are called boost_python.lib (for release builds)
+ and boost_python_debug.lib (for debugging). If you can't
find the libraries, you probably haven't built Boost.Python yet. See Building and Testing on how to do this.
- Python's library can be found in the /libs subdirectory
+ Python's library can be found in the /libs subdirectory
of your Python directory. On Windows it is called pythonXY.lib where X.Y is
your major Python version number.
- Additionally, Python's /include subdirectory has to be added
+ Additionally, Python's /include subdirectory has to be added
to your include path.
@@ -81,56 +81,50 @@ exe embedded_program # name of the executable <library-path>$(PYTHON_LIB_PATH) <find-library>$(PYTHON_EMBEDDED_LIBRARY) ; -
Being able to build is nice, but there is nothing to build yet. Embedding the Python interpreter into one of your C++ programs requires these 4 steps:
-<boost/python.hpp>
+ _main_
+ module.
+ ![]() |
+![]() |
Note |
|---|---|---|
- Note that at this time you must not call Py_Finalize() - to stop the interpreter. This may be fixed in a future version of boost.python. + | ||
+ Note that at this time you must not call Py_Finalize() + to stop the interpreter. This may be fixed in a future version of boost.python. | ||
(Of course, there can be other C++ code between all of these steps.)
---
-- Now that we can embed the interpreter in - our programs, lets see how to put it to use... -
--
-
+ Now that we can embed the interpreter in + our programs, lets see how to put it to use... +
As you probably already know, objects in Python are reference-counted. Naturally,
- the PyObjects of the Python C API are also reference-counted.
+ the PyObjects of the Python C API are also reference-counted.
There is a difference however. While the reference-counting is fully automatic
in Python, the Python C API requires you to do it by
hand. This is messy and especially hard to get right in the presence
@@ -138,10 +132,10 @@ exe embedded_program # name of the executable
and object class templates to
automate the process.
Boost.python provides three related functions to run Python code from C++.
@@ -155,10 +149,10 @@ exe embedded_program # name of the executable and exec_file executes the code contained in the given file.
- The globals and locals parameters are
+ The 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_
+ dictionary of the _main_
module for both parameters.
@@ -171,7 +165,7 @@ exe embedded_program # name of the executable first), and returns it.
- Let's import the _main_
+ Let's import the _main_
module and run some Python code in its namespace:
object main_module = import("__main__"); @@ -186,15 +180,15 @@ 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 -
Often we'd like to have a class to manipulate Python objects. But we have already seen such a class above, and in the previous - section: the aptly named object class and its - derivatives. We've already seen that they can be constructed from a handle. + section: the aptly named
objectclass and its + derivatives. We've already seen that they can be constructed from ahandle. The following examples should further illustrate this fact:object main_module = import("__main__"); @@ -203,7 +197,7 @@ exe embedded_program # name of the executable int five_squared = extract<int>(main_namespace["result"]);- Here we create a dictionary object for the _main_ + 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: @@ -211,10 +205,10 @@ exe embedded_program # name of the executableobject result = eval("5 ** 2"); int five_squared = extract<int>(result);-- +
++ Exception handling -
If an exception occurs in the evaluation of the python expression, error_already_set is thrown: @@ -231,7 +225,7 @@ exe embedded_program # name of the executable }
- The error_already_set exception class doesn't carry any
+ The error_already_set exception class doesn't carry any
information in itself. To find out more about the Python exception that occurred,
you need to use the exception
handling functions of the Python C API in your catch-statement. This
@@ -261,7 +255,7 @@ exe embedded_program # name of the executable
| - |
| - |
- Here, we wrote a C++ class wrapper that exposes the member functions greet
- and set. Now, after building our module as a shared library,
- we may use our class World in Python. Here's a sample Python
+ Here, we wrote a C++ class wrapper that exposes the member functions greet
+ and set. Now, after building our module as a shared library,
+ we may use our class World in Python. Here's a sample Python
session:
@@ -75,11 +75,11 @@ >>> planet.greet() 'howdy' -
- Our previous example didn't have any explicit constructors. Since World
+ Our previous example didn't have any explicit constructors. Since World
is declared as a plain struct, it has an implicit default constructor. Boost.Python
exposes the default constructor by default, which is why we were able to
write
@@ -101,9 +101,9 @@
};
- This time World has no default constructor; our previous
+ This time World has no default constructor; our previous
wrapping code would fail to compile when the library tried to expose it.
- We have to tell class_<World> about the constructor
+ We have to tell class_<World> about the constructor
we want to expose instead.
#include <boost/python.hpp> @@ -118,13 +118,13 @@ }
- init<std::string>() exposes the constructor taking
- in a std::string (in Python, constructors are spelled
- ""_init_"").
+ init<std::string>() exposes the constructor taking
+ in a std::string (in Python, constructors are spelled
+ ""_init_"").
- We can expose additional constructors by passing more init<...>s
- to the def() member function. Say for example we have
+ We can expose additional constructors by passing more init<...>s
+ to the def() member function. Say for example we have
another World constructor taking in two doubles:
class_<World>("World", init<std::string>()) @@ -135,23 +135,23 @@
On the other hand, if we do not wish to expose any constructors at all, we
- may use no_init instead:
+ may use no_init instead:
class_<Abstract>("Abstract", no_init)
- This actually adds an _init_
+ This actually adds an _init_
method which always raises a Python RuntimeError exception.
Data members may also be exposed to Python so that they can be accessed as
attributes of the corresponding Python class. Each data member that we wish
- to be exposed may be regarded as read-only
- or read-write. Consider this class Var:
+ to be exposed may be regarded as read-only
+ or read-write. Consider this class Var:
struct Var { @@ -161,7 +161,7 @@ };
- Our C++ Var class and its data members can be exposed
+ Our C++ Var class and its data members can be exposed
to Python:
class_<Var>("Var", init<std::string>()) @@ -180,16 +180,16 @@ pi is around 3.14
- Note that name is exposed as read-only
- while value is exposed as read-write.
+ 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): - File "<stdin>", line 1, in # -AttributeError: can#t set attribute + File "<stdin>", line 1, in ? +AttributeError: can't set attribute
@@ -211,7 +211,7 @@
However, in Python attribute access is fine; it doesn't neccessarily break
encapsulation to let users handle attributes directly, because the attributes
- can just be a different syntax for a method call. Wrapping our Num
+ can just be a different syntax for a method call. Wrapping our Num
class using Boost.Python:
class_<Num>("Num") @@ -230,8 +230,8 @@ >>> x.rovalue = 2.17 # error!
- Take note that the class property rovalue is exposed as
- read-only since the rovalue
+ Take note that the class property rovalue is exposed as
+ read-only since the rovalue
setter member function is not passed in:
@@ -239,7 +239,7 @@
.add_property("rovalue", &Num::get)
@@ -256,7 +256,7 @@ struct Derived : Base {};
- And a set of C++ functions operating on Base and Derived
+ And a set of C++ functions operating on Base and Derived
object instances:
void b(Base*); @@ -264,15 +264,15 @@ Base* factory() { return new Derived; }
- We've seen how we can wrap the base class Base:
+ We've seen how we can wrap the base class Base:
class_<Base>("Base") /*...*/ ;
- Now we can inform Boost.Python of the inheritance relationship between Derived
- and its base class Base. Thus:
+ Now we can inform Boost.Python of the inheritance relationship between Derived
+ and its base class Base. Thus:
class_<Derived, bases<Base> >("Derived") /*...*/ @@ -281,33 +281,33 @@Doing so, we get some things for free:
---
- - Derived automatically inherits all of Base's Python methods (wrapped C++ - member functions) -
-- -If Base is polymorphic, Derived - objects which have been passed to Python via a pointer or reference to - Base can be passed where a pointer or reference to - Derived is expected. -
++
- + Derived automatically inherits all of Base's Python methods (wrapped + C++ member functions) +
+- + If Base is polymorphic,
Derived+ objects which have been passed to Python via a pointer or reference to +Basecan be passed where a pointer or reference to +Derivedis expected. +- Now, we will expose the C++ free functions b and d - and factory: + Now, we will expose the C++ free functions
bandd+ andfactory:def("b", b); def("d", d); def("factory", factory);- Note that free function factory is being used to generate - new instances of class Derived. In such cases, we use - return_value_policy<manage_new_object> to instruct - Python to adopt the pointer to Base and hold the instance - in a new Python Base object until the the Python object - is destroyed. We will see more of Boost.Python call + Note that free function
factoryis being used to generate + new instances of classDerived. In such cases, we use +return_value_policy<manage_new_object>to instruct + Python to adopt the pointer toBaseand hold the instance + in a new PythonBaseobject until the the Python object + is destroyed. We will see more of Boost.Python call policies later.// Tell Python to take ownership of factory's result @@ -315,13 +315,13 @@ return_value_policy<manage_new_object>());+-In this section, we will learn how to make functions behave polymorphically through virtual functions. Continuing our example, let us add a virtual function - to our Base class: + to our
Baseclass:struct Base { @@ -333,11 +333,11 @@ One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything - to our class Base. Yet, when + to our classBase. Yet, when you have a virtual function that's going to be overridden in Python and called - polymorphically from C++, we'll need to + polymorphically from C++, we'll need to add some scaffoldings to make things work properly. What we'll do is write - a class wrapper that derives from Base + a class wrapper that derives fromBasethat will unintrusively hook into the virtual functions so that a Python override may be called: @@ -350,65 +350,66 @@ };- Notice too that in addition to inheriting from Base, - we also multiply- inherited wrapper<Base> (See Wrapper). - The wrapper template makes + Notice too that in addition to inheriting from
Base, + we also multiply- inheritedwrapper<Base>(See Wrapper). + Thewrappertemplate makes the job of wrapping classes that are meant to overridden in Python, easier.- BaseWrap's overridden virtual member function f - in effect calls the corresponding method of the Python object through get_override. + BaseWrap's overridden virtual member function
f+ in effect calls the corresponding method of the Python object throughget_override.- Finally, exposing Base: + Finally, exposing
Base:class_<BaseWrap, boost::noncopyable>("Base") .def("f", pure_virtual(&Base::f)) ;- pure_virtual signals Boost.Python - that the function f is a +
pure_virtualsignals Boost.Python + that the functionfis a pure virtual function.
- -+ Note + - member function and methods + member function and methods
- Python, like many object oriented languages uses the term methods. - Methods correspond roughly to C++'s member functions + Python, like many object oriented languages uses the term methods. + Methods correspond roughly to C++'s member functions
+-We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python's class - wrapper facilities. If we wish to wrap non-pure-virtual + wrapper facilities. If we wish to wrap non-pure-virtual functions instead, the mechanism is a bit different.
- Recall that in the previous + Recall that in the previous section, we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:
@@ -418,8 +419,8 @@ };- had a pure virtual function f. If, however, its member - function f was not declared as pure virtual: + had a pure virtual function
f. If, however, its member + functionfwas not declared as pure virtual:struct Base { @@ -443,20 +444,21 @@ };- Notice how we implemented BaseWrap::f. Now, - we have to check if there is an override for f. - If none, then we call Base::f(). + Notice how we implemented
BaseWrap::f. Now, + we have to check if there is an override forf. + If none, then we callBase::f().@@ -467,10 +469,10 @@ ;
- Take note that we expose both &Base::f and &BaseWrap::default_f. Boost.Python needs to keep track - of 1) the dispatch function f and 2) the forwarding function - to its default implementation default_f. There's a special - def function for this purpose. + Take note that we expose both
&Base::fand&BaseWrap::default_f. Boost.Python needs to keep track + of 1) the dispatch functionfand 2) the forwarding function + to its default implementationdefault_f. There's a special +deffunction for this purpose.In Python, the results would be as expected: @@ -485,32 +487,32 @@ >>> derived = Derived()
- Calling base.f(): + Calling
base.f():>>> base.f() 0- Calling derived.f(): + Calling
derived.f():>>> derived.f() 42+-- +
++ Python Operators -
C is well known for the abundance of operators. C++ extends this to the extremes by allowing operator overloading. Boost.Python takes advantage of this and makes it easy to wrap C++ operator-powered classes.
- Consider a file position class FilePos and a set of operators + Consider a file position class
FilePosand a set of operators that take on FilePos instances:@@ -541,16 +543,16 @@
The code snippet above is very clear and needs almost no explanation at all. It is virtually the same as the operators' signatures. Just take note that - self refers to FilePos object. Also, not every class - T that you might need to interact with in an operator - expression is (cheaply) default-constructible. You can use other<T>() - in place of an actual T instance when writing "self +
-selfrefers to FilePos object. Also, not every class +Tthat you might need to interact with in an operator + expression is (cheaply) default-constructible. You can useother<T>()+ in place of an actualTinstance when writing "self expressions".- +
++ Special Methods -
Python has a few more Special Methods. Boost.Python supports all of the standard special method names supported by real Python @@ -577,19 +579,19 @@
- -+ Note - What is the business of operator<<? Well, the method str requires the operator<< to do its work (i.e. operator<< - is used by the method defined by def(str(self)). +
+ What is the business of
operator<<? Well, the methodstrrequires theoperator<<to do its work (i.e.operator<<+ is used by the method defined bydef(str(self)).
-
diff --git a/doc/tutorial/doc/html/python/functions.html b/doc/tutorial/doc/html/python/functions.html index e637e77d..ebea6d52 100644 --- a/doc/tutorial/doc/html/python/functions.html +++ b/doc/tutorial/doc/html/python/functions.html @@ -1,13 +1,13 @@ - +Functions - - - - - - + + + + + +
@@ -20,9 +20,9 @@
-+@@ -38,18 +38,12 @@ facilities that will make it even easier for us to expose C++ functions that take advantage of C++ features such as overloading and default arguments. -
+--
-- Read on... -
--
-+ Read on... +
But before you do, you might want to fire up Python 2.2 or later and type - >>> import this. +
>>> import this.>>> import this The Zen of Python, by Tim Peters @@ -68,12 +62,12 @@ In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it Although that way may not be obvious at first unless you're Dutch. Now is better than never. -Although never is often better than right now. +Although never is often better than right now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!-+@@ -121,21 +115,23 @@ Namespaces are one honking great idea -- let's do more of those!
Here's what's happening:
--
- -f is called passing in a reference to y - and a pointer to z -
-- - A reference to y.x is returned -
-- -y is deleted. x is a dangling reference -
-- -x.some_method() is called -
-- BOOM!
++
- +
+fis called passing in a reference toy+ and a pointer toz+- + A reference to
+y.xis returned +- +
+yis deleted.xis a dangling reference +- +
+x.some_method()is called +- + BOOM! +
We could copy result into a new object: @@ -163,7 +159,7 @@ Namespaces are one honking great idea -- let's do more of those! };
- Notice that the data member z is held by class Y using + Notice that the data member
zis held by class Y using a raw pointer. Now we have a potential dangling pointer problem inside Y:>>> x = f(y, z) # y refers to z @@ -171,7 +167,7 @@ Namespaces are one honking great idea -- let's do more of those! >>> y.z_value() # CRASH!- For reference, here's the implementation of f again: + For reference, here's the implementation of
fagain:X& f(Y& y, Z* z) { @@ -182,35 +178,38 @@ Namespaces are one honking great idea -- let's do more of those!Here's what's happening:
--
- -f is called passing in a reference to y - and a pointer to z -
-- - A pointer to z is held by y -
-- - A reference to y.x is returned -
-- -z is deleted. y.z is a dangling pointer -
-- -y.z_value() is called -
-- -z->value() is called -
-- BOOM!
+-+
- +
+fis called passing in a reference toy+ and a pointer toz+- + A pointer to
+zis held byy+- + A reference to
+y.xis returned +- +
+zis deleted.y.zis a dangling + pointer +- +
+y.z_value()is called +- +
+z->value()is called +- + BOOM! +
- +
++ Call Policies -
Call Policies may be used in situations such as the example detailed above. - In our example, return_internal_reference and with_custodian_and_ward + In our example,
return_internal_referenceandwith_custodian_and_wardare our friends:def("f", f, @@ -218,25 +217,25 @@ Namespaces are one honking great idea -- let's do more of those! with_custodian_and_ward<1, 2> >());- What are the 1 and 2 parameters, you + What are the
1and2parameters, you ask?return_internal_reference<1- Informs Boost.Python that the first argument, in our case Y& - y, is the owner of the returned reference: X&. - The "1" simply specifies the first argument. - In short: "return an internal reference X& owned - by the 1st argument Y& y". + Informs Boost.Python that the first argument, in our case
Y& + y, is the owner of the returned reference:X&. + The "1" simply specifies the first argument. + In short: "return an internal referenceX&owned + by the 1st argumentY& y".with_custodian_and_ward<1, 2>Informs Boost.Python that the lifetime of the argument indicated by ward - (i.e. the 2nd argument: Z* z) is dependent on the lifetime - of the argument indicated by custodian (i.e. the 1st argument: Y& - y). + (i.e. the 2nd argument:
Z* z) is dependent on the lifetime + of the argument indicated by custodian (i.e. the 1st argument:Y& + y).It is also important to note that we have defined two policies above. Two @@ -250,42 +249,44 @@ Namespaces are one honking great idea -- let's do more of those! Here is the list of predefined call policies. A complete reference detailing these can be found here.
--
- -with_custodian_and_ward: Ties lifetimes - of the arguments -
-- -with_custodian_and_ward_postcall: Ties - lifetimes of the arguments and results -
-- -return_internal_reference: Ties lifetime - of one argument to that of result -
-- -return_value_policy<T> with T one of:
--
- -reference_existing_object: naive (dangerous) - approach -
-- -copy_const_reference: Boost.Python - v1 approach -
-- -copy_non_const_reference: -
-- -manage_new_object: Adopt a pointer - and hold the instance -
++
- + with_custodian_and_ward: Ties lifetimes + of the arguments +
+- + with_custodian_and_ward_postcall: Ties + lifetimes of the arguments and results +
+- + return_internal_reference: Ties lifetime + of one argument to that of result +
+- + return_value_policy<T> with T one of: +
+-+
- + reference_existing_object: naive + (dangerous) approach +
+- + copy_const_reference: Boost.Python + v1 approach +
+- + copy_non_const_reference: +
+- + manage_new_object: Adopt a pointer + and hold the instance +
+-@@ -347,31 +348,31 @@ Namespaces are one honking great idea -- let's do more of those! .def("f", fx4)
+Boost.Python wraps (member) function pointers. Unfortunately, C++ function - pointers carry no default argument info. Take a function f + pointers carry no default argument info. Take a function
fwith default arguments:int f(int, double = 3.14, char const* = "hello");- But the type of a pointer to the function f has no information + But the type of a pointer to the function
fhas no information about its default arguments:int(*g)(int,double,char const*) = f; // defaults lost!- When we pass this function pointer to the def function, + When we pass this function pointer to the
deffunction, there is no way to retrieve the default arguments:def("f", f); // defaults lost!Because of this, when wrapping C++ code, we had to resort to manual wrapping - as outlined in the previous section, + as outlined in the previous section, or writing thin wrappers:
// write "thin wrappers" @@ -388,18 +389,18 @@ Namespaces are one honking great idea -- let's do more of those!When you want to wrap functions (or member functions) that either:
---
- - have default arguments, or -
-- - are overloaded with a common sequence of initial arguments -
+-+
- + have default arguments, or +
+- + are overloaded with a common sequence of initial arguments +
- +
++ BOOST_PYTHON_FUNCTION_OVERLOADS -
Boost.Python now has a way to make it easier. For instance, given a function:
@@ -415,18 +416,18 @@ Namespaces are one honking great idea -- let's do more of those!will automatically create the thin wrappers for us. This macro will create - a class foo_overloads that can be passed on to def(...). + a class
foo_overloadsthat can be passed on todef(...). The third and fourth macro argument are the minimum arguments and maximum - arguments, respectively. In our foo function the minimum - number of arguments is 1 and the maximum number of arguments is 4. The def(...) + arguments, respectively. In ourfoofunction the minimum + number of arguments is 1 and the maximum number of arguments is 4. Thedef(...)function will automatically add all the foo variants for us:def("foo", foo, foo_overloads());-- +
++ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS -
Objects here, objects there, objects here there everywhere. More frequently than anything else, we need to expose member functions of our classes to @@ -435,7 +436,7 @@ Namespaces are one honking great idea -- let's do more of those! play. Another macro is provided to make this a breeze.
- Like BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS + Like
@@ -454,11 +455,11 @@ Namespaces are one honking great idea -- let's do more of those!BOOST_PYTHON_FUNCTION_OVERLOADS,BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADSmay be used to automatically create the thin wrappers for wrapping member functions. Let's have an example:BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)- will generate a set of thin wrappers for george's wack_em + will generate a set of thin wrappers for george's
wack_emmember function accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and fourth macro argument). The thin wrappers are all enclosed - in a class named george_overloads that can then be used - as an argument to def(...): + in a class namedgeorge_overloadsthat can then be used + as an argument todef(...):.def("wack_em", &george::wack_em, george_overloads());@@ -466,13 +467,13 @@ Namespaces are one honking great idea -- let's do more of those! See the overloads reference for details. -- +
++ init and optional -
A similar facility is provided for class constructors, again, with default - arguments or a sequence of overloads. Remember init<...>? + arguments or a sequence of overloads. Remember
init<...>? For example, given a class X with a constructor:struct X @@ -487,16 +488,16 @@ Namespaces are one honking great idea -- let's do more of those!.def(init<int, optional<char, std::string, double> >())- Notice the use of init<...> and optional<...> + Notice the use of
init<...>andoptional<...>to signify the default (optional arguments).+- It was mentioned in passing in the previous section that BOOST_PYTHON_FUNCTION_OVERLOADS - and BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS can also be + It was mentioned in passing in the previous section that
@@ -535,24 +536,24 @@ Namespaces are one honking great idea -- let's do more of those! Notice though that we have a situation now where we have a minimum of zero (0) arguments and a maximum of 3 arguments. -BOOST_PYTHON_FUNCTION_OVERLOADS+ andBOOST_PYTHON_MEMBER_FUNCTION_OVERLOADScan also be used for overloaded functions and member functions with a common sequence of initial arguments. Here is an example:- +
++ Manual Wrapping -
- It is important to emphasize however that the overloaded - functions must have a common sequence of initial arguments. Otherwise, + It is important to emphasize however that the overloaded + functions must have a common sequence of initial arguments. Otherwise, our scheme above will not work. If this is not the case, we have to wrap - our functions manually. + our functions manually.
Actually, we can mix and match manual wrapping of overloaded functions and - automatic wrapping through BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS - and its sister, BOOST_PYTHON_FUNCTION_OVERLOADS. Following - up on our example presented in the section on + automatic wrapping through
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS+ and its sister,BOOST_PYTHON_FUNCTION_OVERLOADS. Following + up on our example presented in the section on overloading, since the first 4 overload functins have a common sequence - of initial arguments, we can use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS - to automatically wrap the first three of the defs and + of initial arguments, we can useBOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS+ to automatically wrap the first three of thedefs and manually wrap just the last. Here's how we'll do this:BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4) @@ -573,7 +574,7 @@ Namespaces are one honking great idea -- let's do more of those!
-
diff --git a/doc/tutorial/doc/html/python/hello.html b/doc/tutorial/doc/html/python/hello.html index 5fcc66ec..35fc56e0 100644 --- a/doc/tutorial/doc/html/python/hello.html +++ b/doc/tutorial/doc/html/python/hello.html @@ -1,13 +1,13 @@ - -Building Hello World - - - - - - + +Building Hello World + + + + + +
@@ -20,34 +20,34 @@
-+-- +
++ From Start To Finish -
Now the first thing you'd want to do is to build the Hello World module and try it for yourself in Python. In this section, we will outline the steps necessary to achieve that. We will use the build tool that comes bundled with every boost - distribution: bjam. + distribution: bjam.
- -+ Note + - Building without bjam + Building without bjam
Besides bjam, there are of course other ways to get your module built. What's written here should not be taken as "the one and only way". There - are of course other build tools apart from bjam. + are of course other build tools apart from
bjam.Take note however that the preferred build tool for Boost.Python is bjam. @@ -65,65 +65,59 @@ and run a python program using the extension.
- The tutorial example can be found in the directory: libs/python/example/tutorial. + The tutorial example can be found in the directory:
-libs/python/example/tutorial. There, you can find:-
- - hello.cpp -
-- - hello.py -
-- - Jamroot -
++
- + hello.cpp +
+- + hello.py +
+- + Jamroot +
- The hello.cpp file is our C++ hello world example. The - Jamroot is a minimalist bjam script - that builds the DLLs for us. Finally, hello.py is our Python - program that uses the extension in hello.cpp. + The
hello.cppfile is our C++ hello world example. The +Jamrootis a minimalist bjam script + that builds the DLLs for us. Finally,hello.pyis our Python + program that uses the extension inhello.cpp.Before anything else, you should have the bjam executable in your boost directory - or somewhere in your path such that bjam can be executed + or somewhere in your path such that
-bjamcan be executed 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! -
![]()
Here is our minimalist - Jamroot file. Simply copy the file and tweak use-project boost + Jamroot file. Simply copy the file and tweak
use-project boostto where your boost root directory is and your OK.The comments contained in the Jamrules file above should be sufficient to get you going.
-- +
++ Running bjam -
bjam is run using your operating system's command line interpreter.
-+--
-- Start it up. -
--
-+ Start it up. +
A file called user-config.jam in your home directory is used to configure your tools. In Windows, your home directory can be found by typing: @@ -144,13 +138,13 @@ using python : 2.4 : C:/dev/toolsPython ;
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.- Now we are ready... Be sure to cd to libs/python/example/tutorial - where the tutorial "hello.cpp" and the "Jamroot" + Now we are ready... Be sure to
cdtolibs/python/example/tutorial+ where the tutorial"hello.cpp"and the"Jamroot"is situated.@@ -179,30 +173,13 @@ bjam Or something similar. If all is well, you should now have built the DLLs and run the Python program.
---
- -- Note -- - Starting from Boost 1.35, bjam erases the generated executables (e.g. pyd - file) after the test has concluded to conserve disk space. To keep bjam from - doing that, pass --preserve-test-targets to bjam. -
+--
-- There you go... Have fun! -
--
-+ There you go... Have fun! +
-
diff --git a/doc/tutorial/doc/html/python/iterators.html b/doc/tutorial/doc/html/python/iterators.html index 9968cb73..3f87ab77 100644 --- a/doc/tutorial/doc/html/python/iterators.html +++ b/doc/tutorial/doc/html/python/iterators.html @@ -1,13 +1,13 @@ - +Iterators - - - - + + + + - +
@@ -20,9 +20,9 @@
-+@@ -30,37 +30,37 @@ iterators, but these are two very different beasts.
- C++ iterators: + C++ iterators:
--
- - C++ has 5 type categories (random-access, bidirectional, forward, input, - output) -
-- - There are 2 Operation categories: reposition, access -
-- - A pair of iterators is needed to represent a (first/last) range. -
++
- + C++ has 5 type categories (random-access, bidirectional, forward, input, + output) +
+- + There are 2 Operation categories: reposition, access +
+- + A pair of iterators is needed to represent a (first/last) range. +
- Python Iterators: + Python Iterators:
--
- - 1 category (forward) -
-- - 1 operation category (next()) -
-- - Raises StopIteration exception at end -
++
- + 1 category (forward) +
+- + 1 operation category (next()) +
+- + Raises StopIteration exception at end +
- The typical Python iteration protocol: for y - in x... is as follows: + The typical Python iteration protocol:
for y + in x...is as follows:@@ -73,7 +73,7 @@
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 + 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:@@ -88,42 +88,42 @@
.def("__iter__", iterator<vector<int> >())- range + range
We can create a Python savvy iterator using the range function:
--
- - range(start, finish) -
-- - range<Policies,Target>(start, finish) -
++
- + range(start, finish) +
+- + range<Policies,Target>(start, finish) +
Here, start/finish may be one of:
--
- - member data pointers -
-- - member function pointers -
-- - adaptable function object (use Target parameter) -
++
- + member data pointers +
+- + member function pointers +
+- + adaptable function object (use Target parameter) +
- iterator + iterator
-+
- - iterator<T, Policies>() -
- + iterator<T, Policies>() +
- Given a container T, iterator is a shortcut that simply - calls range with &T::begin, &T::end. + Given a container
T, iterator is a shortcut that simply + callsrangewith &T::begin, &T::end.Let's put this into action... Here's an example from some hypothetical bogon @@ -147,14 +147,14 @@ .property("bogons", range(&F::b_begin, &F::b_end));
- stl_input_iterator + stl_input_iterator
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes we wish to go the other way, though: we'd like to pass a Python sequence to an STL algorithm or use it to initialize an STL container. We need to make - a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>. - Consider how we might implement a function that exposes std::list<int>::assign() to Python: + a Python iterator look like an STL iterator. For that, we use
stl_input_iterator<>. + Consider how we might implement a function that exposesstd::list<int>::assign()to Python:@@ -172,7 +172,7 @@ ;
- Now in Python, we can assign any integer sequence to list_int + Now in Python, we can assign any integer sequence to
list_intobjects:@@ -183,7 +183,7 @@
-
diff --git a/doc/tutorial/doc/html/python/object.html b/doc/tutorial/doc/html/python/object.html index 533ab873..d1cc7138 100644 --- a/doc/tutorial/doc/html/python/object.html +++ b/doc/tutorial/doc/html/python/object.html @@ -1,11 +1,11 @@ - -Object Interface - - - - + +Object Interface + + + + @@ -20,9 +20,9 @@
-+@@ -35,26 +35,26 @@ Python is dynamically typed, unlike C++ which is statically typed. Python variables may hold an integer, a float, list, dict, tuple, str, long etc., among other things. In the viewpoint of Boost.Python and C++, these Pythonic variables - are just instances of class object. We will see in this + are just instances of class
object. We will see in this chapter how to deal with Python objects.As mentioned, one of the goals of Boost.Python is to provide a bidirectional mapping between C++ and Python while maintaining the Python feel. Boost.Python - C++ objects are as close as possible to Python. This should + C++
objects are as close as possible to Python. This should minimize the learning curve significantly.-
+-- Class object wraps PyObject*. All the - intricacies of dealing with PyObjects such as managing - reference counting are handled by the object class. C++ - object interoperability is seamless. Boost.Python C++ objects + Class
objectwrapsPyObject*. All the + intricacies of dealing withPyObjects such as managing + reference counting are handled by theobjectclass. C++ + object interoperability is seamless. Boost.Python C++objects can in fact be explicitly constructed from any C++ object.@@ -93,57 +93,57 @@ in C++, the look and feel should be immediately apparent to the Python coder.
+- Boost.Python comes with a set of derived object types + Boost.Python comes with a set of derived
-objecttypes corresponding to that of Python's:--
- - list -
-- - dict -
-- - tuple -
-- - str -
-- - long_ -
-- - enum -
++
- + list +
+- + dict +
+- + tuple +
+- + str +
+- + long_ +
+- + enum +
- These derived object types act like real Python types. + These derived
objecttypes act like real Python types. For instance:str(1) ==> "1"- Wherever appropriate, a particular derived object has - corresponding Python type's methods. For instance, dict - has a keys() method: + Wherever appropriate, a particular derived
objecthas + corresponding Python type's methods. For instance,dict+ has akeys()method:d.keys()- make_tuple is provided for declaring tuple literals. +
make_tupleis provided for declaring tuple literals. Example:make_tuple(123, 'D', "Hello, World", 0.0);- In C++, when Boost.Python objects are used as arguments + In C++, when Boost.Python
objects are used as arguments to functions, subtype matching is required. For example, when a function - f, as declared below, is wrapped, it will only accept - instances of Python's str type and subtypes. +f, as declared below, is wrapped, it will only accept + instances of Python'sstrtype and subtypes.void f(str name) { @@ -164,15 +164,18 @@object msg = "%s is bigger than %s" % make_tuple(NAME,name);- 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 + Demonstrates that you can write the C++ equivalent of
-"format" + % x,y,zin Python, which is useful since there's no easy way to do that in std C++.Python:
@@ -185,12 +188,12 @@dict d(x.attr("__dict__")); // copies x.__dict__ d['whatever'] = 3; // modifies the copy-- +
++ class_<T> as objects -
- Due to the dynamic nature of Boost.Python objects, any class_<T> + Due to the dynamic nature of Boost.Python objects, any
@@ -206,19 +209,19 @@ assert(vec345.attr("length") == 5.0);class_<T>may also be one of these types! The following code snippet wraps the class (type) object.+-At some point, we will need to get C++ values out of object instances. This - can be achieved with the extract<T> function. Consider + can be achieved with the
extract<T>function. Consider the following:double x = o.attr("length"); // compile error- In the code above, we got a compiler error because Boost.Python object - can't be implicitly converted to doubles. Instead, what + In the code above, we got a compiler error because Boost.Python
object+ can't be implicitly converted todoubles. Instead, what we wanted to do above can be achieved by writing:double l = extract<double>(o.attr("length")); @@ -227,14 +230,14 @@The first line attempts to extract the "length" attribute of the - Boost.Python object. The second line attempts to extract - the Vec2 object from held by the Boost.Python object. + Boost.Python
object. The second line attempts to extract + theVec2object from held by the Boost.Pythonobject.Take note that we said "attempt to" above. What if the Boost.Python - object does not really hold a Vec2 +
@@ -243,20 +246,20 @@ Vec2& v = x(); ...objectdoes not really hold aVec2type? This is certainly a possibility considering the dynamic nature of Python - objects. To be on the safe side, if the C++ type can't +objects. To be on the safe side, if the C++ type can't be extracted, an appropriate exception is thrown. To avoid an exception, we need to test for extractibility:-
The astute reader might have noticed that the extract<T> +
The astute reader might have noticed that the
extract<T>facility in fact solves the mutable copying problem:dict d = extract<dict>(x.attr("__dict__")); d["whatever"] = 3; // modifies x.__dict__ !+Boost.Python has a nifty facility to capture and wrap C++ enums. While Python - has no enum type, we'll often want to expose our C++ enums - to Python as an int. Boost.Python's enum facility makes + has no
enumtype, we'll often want to expose our C++ enums + to Python as anint. Boost.Python's enum facility makes this easy while taking care of the proper conversions from Python's dynamic typing to C++'s strong static typing (in C++, ints cannot be implicitly converted to enums). To illustrate, given a C++ enum: @@ -273,18 +276,18 @@can be used to expose to Python. The new enum type is created in the current - scope(), which is usually the current module. The snippet - above creates a Python class derived from Python's int +
scope(), which is usually the current module. The snippet + above creates a Python class derived from Python'sinttype which is associated with the C++ type passed as its first parameter.