From 1d5fb9798136c625127a818c3f0de496e2c0e996 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Thu, 10 Oct 2002 07:13:17 +0000 Subject: [PATCH] Tutorial updates [SVN r15840] --- doc/tutorial/doc/basic_interface.html | 10 +- doc/tutorial/doc/building_hello_world.html | 17 ++- doc/tutorial/doc/call_policies.html | 2 +- .../class_operators_special_functions.html | 18 +++- doc/tutorial/doc/class_virtual_functions.html | 6 +- doc/tutorial/doc/derived_object_types.html | 2 +- doc/tutorial/doc/enums.html | 95 +++++++++++++++++ doc/tutorial/doc/extracting_c___objects.html | 6 +- doc/tutorial/doc/iterators.html | 8 +- doc/tutorial/doc/object_interface.html | 2 +- doc/tutorial/doc/quickstart.txt | 100 ++++++++++++++---- doc/tutorial/index.html | 5 + 12 files changed, 227 insertions(+), 44 deletions(-) create mode 100644 doc/tutorial/doc/enums.html diff --git a/doc/tutorial/doc/basic_interface.html b/doc/tutorial/doc/basic_interface.html index cb4a28f4..a9326c80 100644 --- a/doc/tutorial/doc/basic_interface.html +++ b/doc/tutorial/doc/basic_interface.html @@ -32,11 +32,11 @@ Class object wraps PyObject*. All the intricacies of dealing w

To illustrate, this Python code snippet:

-    def f(x, f):
+    def f(x, y):
          if (y == 'foo'):
              x[3:7] = 'bar'
          else:
-             x.items += f(3, x)
+             x.items += y(3, x)
          return x
 
     def getfunc():
@@ -45,11 +45,11 @@ To illustrate, this Python code snippet:

Can be rewritten in C++ using Boost.Python facilities this way:

-    object f(object x, object f) {
-         if (f == "foo")
+    object f(object x, object y) {
+         if (y == "foo")
              x.slice(3,7) = "bar";
          else
-             x.attr("items") += f(3, x);
+             x.attr("items") += y(3, x);
          return x;
     }
     object getfunc() {
diff --git a/doc/tutorial/doc/building_hello_world.html b/doc/tutorial/doc/building_hello_world.html
index 8595ea56..297757ea 100644
--- a/doc/tutorial/doc/building_hello_world.html
+++ b/doc/tutorial/doc/building_hello_world.html
@@ -29,6 +29,17 @@ 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 shall outline the steps
 necessary to achieve that. We shall use the build tool that comes bundled
 with every boost distribution: 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. +

We shall skip over the details. Our objective will be to simply create the hello world module and run it in Python. For a complete reference to @@ -47,11 +58,13 @@ The hello.cpp file is our C++ hello world example. The Jamfile 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 most +directory or somewhere in your path such that bjam can be executed in +the command line. Pre-built Boost.Jam executables are available for most platforms. For example, a pre-built Microsoft Windows bjam executable can be downloaded here. -The complete list of bjam pre-built executables can be found +The complete list of bjam pre-built +executables can be found here.

Lets Jam!

diff --git a/doc/tutorial/doc/call_policies.html b/doc/tutorial/doc/call_policies.html index 194097df..4f836700 100644 --- a/doc/tutorial/doc/call_policies.html +++ b/doc/tutorial/doc/call_policies.html @@ -131,7 +131,7 @@ first argument. In short: "return an internal reference X& own

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: Z* z).

+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 or more policies can be composed by chaining. Here's the general syntax:

diff --git a/doc/tutorial/doc/class_operators_special_functions.html b/doc/tutorial/doc/class_operators_special_functions.html index 74a952a2..ca7f6c0b 100644 --- a/doc/tutorial/doc/class_operators_special_functions.html +++ b/doc/tutorial/doc/class_operators_special_functions.html @@ -25,7 +25,7 @@

Python Operators

-C is well known for the abundance of oparators. C++ extends this to the +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.

@@ -76,14 +76,22 @@ that correspond to these Python special functions. Example:

ostream& operator<<(ostream&,Rational); class_<Rational>() - .def(float_(self)) // __float__ - .def(pow(self)) // __pow__ - .def(abs(self)) // __abs__ - .def(str(self)) // __str__ + .def(float_(self)) // __float__ + .def(pow(self, other<Rational>)) // __pow__ + .def(abs(self)) // __abs__ + .def(str(self)) // __str__ ;

Need we say more?

+ + + + +
+ What is the business of operator<< .def(str(self))? +Well, the method str requires the operator<< to do its work (i.e. +operator<< is used by the method defined by def(str(self)).
diff --git a/doc/tutorial/doc/class_virtual_functions.html b/doc/tutorial/doc/class_virtual_functions.html index 72c3fe3d..6116678a 100644 --- a/doc/tutorial/doc/class_virtual_functions.html +++ b/doc/tutorial/doc/class_virtual_functions.html @@ -137,14 +137,14 @@ Calling derived.f():

Will yield the expected result. Finally, calling calling the free function call_f with derived as argument:

-    >>> call_f(derived())
+    >>> call_f(derived)
     42
 

Will also yield the expected result.

Here's what's happening:

-
  1. call_f(derived()) is called in Python
  2. This corresponds to def("call_f", call_f);. Boost.Python dispatches this call.
  3. int call_f(Base& b) { return b.f(); } accepts the call.
  4. The overridden virtual function f of BaseWrap is called.
  5. call_method<int>(self, "f"); dispatches the call back to Python.
  6. def f(self): return 42 is finally called.

+

  1. call_f(derived) is called in Python
  2. This corresponds to def("call_f", call_f);. Boost.Python dispatches this call.
  3. int call_f(Base& b) { return b.f(); } accepts the call.
  4. The overridden virtual function f of BaseWrap is called.
  5. call_method<int>(self, "f"); dispatches the call back to Python.
  6. def f(self): return 42 is finally called.

Rewind back to our Base class, if its member function f was not declared as pure virtual:

@@ -207,7 +207,7 @@ Calling call_f, passing in a base object:

Calling call_f, passing in a derived object:

-    >>> call_f(derived())
+    >>> call_f(derived)
     42
 
diff --git a/doc/tutorial/doc/derived_object_types.html b/doc/tutorial/doc/derived_object_types.html index 303774f7..54ffccb3 100644 --- a/doc/tutorial/doc/derived_object_types.html +++ b/doc/tutorial/doc/derived_object_types.html @@ -27,7 +27,7 @@

Boost.Python comes with a set of derived object types corresponding to that of Python's:

-
  • list
  • dict
  • tuple
  • str
  • long_

+

  • list
  • dict
  • tuple
  • str
  • long_
  • enum

These derived object types act like real Python types. For instance:

     str(1) ==> "1"
diff --git a/doc/tutorial/doc/enums.html b/doc/tutorial/doc/enums.html
new file mode 100644
index 00000000..7626c948
--- /dev/null
+++ b/doc/tutorial/doc/enums.html
@@ -0,0 +1,95 @@
+
+
+
+Enums
+
+
+
+
+
+
+ + + + +
+ + Enums +
+
+ + + + + + +
+

+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 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). Boost.Python's enum facility makes this +easy. To illustrate, given a C++ enum:

+
+    enum choice { red, blue };
+
+

+the construct:

+
+    enum_<choice>("choice")
+        .value("red", red)
+        .value("blue", blue)
+        ;
+
+

+can be used to expose it 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 type which is +associated with the C++ type passed as its first parameter.

+ + + + +
+ what is a scope?

The scope is a class that has an +associated global Python object which controls the Python namespace in +which new extension classes and wrapped functions will be defined as +attributes. Details can be found +here
+

+You can access those values in Python as

+
+    >>> my_module.choice.red
+    my_module.choice.red
+
+

+where my_module is the module where the enum is declared. You can 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")
+        .value("red", red)
+        .value("blue", blue)
+        ;
+
+ + + + + + +
+
+
+ + diff --git a/doc/tutorial/doc/extracting_c___objects.html b/doc/tutorial/doc/extracting_c___objects.html index a6ba5444..36b8bf85 100644 --- a/doc/tutorial/doc/extracting_c___objects.html +++ b/doc/tutorial/doc/extracting_c___objects.html @@ -4,7 +4,7 @@ Extracting C++ objects - + @@ -21,7 +21,7 @@ - +

@@ -66,7 +66,7 @@ facility in fact solves the mutable copying problem:

- +
diff --git a/doc/tutorial/doc/iterators.html b/doc/tutorial/doc/iterators.html index 7e4282cb..00e8dc44 100644 --- a/doc/tutorial/doc/iterators.html +++ b/doc/tutorial/doc/iterators.html @@ -3,7 +3,7 @@ Iterators - + @@ -20,7 +20,7 @@ - +
@@ -34,7 +34,7 @@ iterators, but these are two very different beasts.

  • 1 category (forward)
  • 1 operation category (next())
  • Raises StopIteration exception at end

The typical Python iteration protocol: for y in x... is as follows:

-    iter iter = x.__iter__()    #get iterator
+    iter = x.__iter__()         #get iterator
     try:
         while 1:
         y = iter.next()         #get each item
@@ -87,7 +87,7 @@ Now, our C++ Wrapper:

- +
diff --git a/doc/tutorial/doc/object_interface.html b/doc/tutorial/doc/object_interface.html index 2279a60c..d18a40bb 100644 --- a/doc/tutorial/doc/object_interface.html +++ b/doc/tutorial/doc/object_interface.html @@ -26,7 +26,7 @@

Python is dynamically typed, unlike C++ which is statically typed. Python -variables may hold an integers, a float, list, dict, tuple, str, long etc., +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 shall see in this chapter how to deal with Python objects.

diff --git a/doc/tutorial/doc/quickstart.txt b/doc/tutorial/doc/quickstart.txt index a8176ec1..8541612a 100644 --- a/doc/tutorial/doc/quickstart.txt +++ b/doc/tutorial/doc/quickstart.txt @@ -57,6 +57,13 @@ try it for yourself in Python. In this section, we shall outline the steps necessary to achieve that. We shall use the build tool that comes bundled with every boost distribution: [*bjam]. +[blurb __detail__ [*Building without bjam][br][br] + +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]. +] + We shall skip over the details. Our objective will be to simply create the hello world module and run it in Python. For a complete reference to building Boost.Python, check out: [@../../building.html building.html]. @@ -82,10 +89,12 @@ 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 most +directory or somewhere in your path such that [^bjam] can be executed in +the command line. 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]. +The complete list of bjam pre-built +executables can be found [@../../../../../tools/build/index.html#Jam here]. [h2 Lets Jam!] [$theme/jam.png] @@ -540,14 +549,14 @@ Calling [^derived.f()]: Will yield the expected result. Finally, calling calling the free function [^call_f] with [^derived] as argument: - >>> call_f(derived()) + >>> call_f(derived) 42 Will also yield the expected result. Here's what's happening: -# [^call_f(derived())] is called in Python +# [^call_f(derived)] is called in Python # This corresponds to [^def("call_f", call_f);]. Boost.Python dispatches this call. # [^int call_f(Base& b) { return b.f(); }] accepts the call. # The overridden virtual function [^f] of [^BaseWrap] is called. @@ -609,14 +618,14 @@ Calling [^call_f], passing in a [^base] object: Calling [^call_f], passing in a [^derived] object: - >>> call_f(derived()) + >>> call_f(derived) 42 [page:1 Class Operators/Special Functions] [h2 Python Operators] -C is well known for the abundance of oparators. C++ extends this to the +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. @@ -667,14 +676,18 @@ that correspond to these Python ['special functions]. Example: ostream& operator<<(ostream&,Rational); class_() - .def(float_(self)) // __float__ - .def(pow(self)) // __pow__ - .def(abs(self)) // __abs__ - .def(str(self)) // __str__ + .def(float_(self)) // __float__ + .def(pow(self, other)) // __pow__ + .def(abs(self)) // __abs__ + .def(str(self)) // __str__ ; Need we say more? +[blurb __detail__ What is the business of [^operator<<] [^.def(str(self))]? +Well, the method [^str] requires the [^operator<<] to do its work (i.e. +[^operator<<] is used by the method defined by def(str(self)).] + [page Functions] In this chapter, we'll look at Boost.Python powered functions in closer @@ -827,7 +840,7 @@ first argument. In short: "return an internal reference [^X&] owned by the 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: [^Z* z]). +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 or more policies can be composed by chaining. Here's the general syntax: @@ -928,7 +941,7 @@ Notice the use of [^init<...>] and [^optional<...>] to signify the default [page Object Interface] Python is dynamically typed, unlike C++ which is statically typed. Python -variables may hold an integers, a float, list, dict, tuple, str, long etc., +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 shall see in this chapter how to deal with Python objects. @@ -949,11 +962,11 @@ Class [^object] wraps [^PyObject*]. All the intricacies of dealing with To illustrate, this Python code snippet: - def f(x, f): + def f(x, y): if (y == 'foo'): x[3:7] = 'bar' else: - x.items += f(3, x) + x.items += y(3, x) return x def getfunc(): @@ -961,11 +974,11 @@ To illustrate, this Python code snippet: Can be rewritten in C++ using Boost.Python facilities this way: - object f(object x, object f) { - if (f == "foo") + object f(object x, object y) { + if (y == "foo") x.slice(3,7) = "bar"; else - x.attr("items") += f(3, x); + x.attr("items") += y(3, x); return x; } object getfunc() { @@ -986,6 +999,7 @@ that of Python's: * tuple * str * long_ +* enum These derived [^object] types act like real Python types. For instance: @@ -1084,11 +1098,59 @@ test for extractibility: Vec2& v = x(); ... __tip__ The astute reader might have noticed that the [^extract] -facility in fact solves mutable copying problem: +facility in fact solves the mutable copying problem: dict d = extract(x.attr("__dict__")); d['whatever'] = 3; # modifies x.__dict__ ! + +[page:1 Enums] + +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] 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). Boost.Python's enum facility makes this +easy. To illustrate, given a C++ enum: + + enum choice { red, blue }; + +the construct: + + enum_("choice") + .value("red", red) + .value("blue", blue) + ; + +can be used to expose it 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] type which is +associated with the C++ type passed as its first parameter. + +[blurb __detail__ [*what is a scope?][br][br] The scope is a class that has an +associated global Python object which controls the Python namespace in +which new extension classes and wrapped functions will be defined as +attributes. Details can be found [@../../v2/scope.html here]] + +You can access those values in Python as + + >>> my_module.choice.red + my_module.choice.red + +where my_module is the module where the enum is declared. You can create a +new scope around a class: + + scope in_X(class_("X") + .def( ... ) + .def( ... ) + ); + + // Expose X::nested as X.nested + enum_("nested") + .value("red", red) + .value("blue", blue) + ; + [page Iterators] In C++, and STL in particular, we see iterators everywhere. Python also has @@ -1108,7 +1170,7 @@ iterators, but these are two very different beasts. The typical Python iteration protocol: [^[*for y in x...]] is as follows: - iter iter = x.__iter__() # get iterator + iter = x.__iter__() # get iterator try: while 1: y = iter.next() # get each item diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html index 14554d97..4e1333da 100644 --- a/doc/tutorial/index.html +++ b/doc/tutorial/index.html @@ -100,6 +100,11 @@ Extracting C++ objects + + + Enums + + Iterators