From 2a530bb9d28993196405a2eb3f300ab3f296f99e Mon Sep 17 00:00:00 2001
From: Joel de Guzman
+It was mentioned in passing in the previous section that
+BOOST_PYTHON_FUNCTION_OVERLOADS and BOOST_PYTHON_FUNCTION_OVERLOADS
+can also be used for overloaded functions and member functions with a
+common sequence of initial arguments. Here is an example:
+Like in the previous section, we can generate thin wrappers for these
+overloaded functions in one-shot:
+Then...
+Notice though that we have a situation now where we have a minimum of zero
+(0) arguments and a maximum of 3 arguments.
+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.
+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 overloading, since the
+first overload has default arguments, we can use
+BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS to automatically wrap the first
+three of the defs above and manually wrap just the last. Here's how
+we'll do this:
+Create a member function pointers as above for both X::f overloads:
+Then... Copyright © 2002-2003 David Abrahams
@@ -156,7 +156,7 @@ here.
@@ -112,118 +112,11 @@ In Python, let us try to instantiate our Base class:
+
+
+
+
+
+
+ Auto-Overloading
+
+
+
+
+
+
+
+ 
+ 
+ 
+
+ void foo()
+ {
+ /*...*/
+ }
+
+ void foo(bool a)
+ {
+ /*...*/
+ }
+
+ void foo(bool a, int b)
+ {
+ /*...*/
+ }
+
+ void foo(bool a, int b, char c)
+ {
+ /*...*/
+ }
+
+
+ BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
+
+
+ .def("foo", foo, foo_overloads());
+
Manual Wrapping
+
+ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
+
+
+ bool (X::*fx1)(int, double, char) = &X::f;
+ int (X::*fx2)(int, int, int) = &X::f;
+
+
+ .def("f", fx1, xf_overloads());
+ .def("f", fx2)
+
+
+
+
+
+ 
+ 
+ 
+
Copyright © 2002-2003 Joel de Guzman
+Permission to copy, use, modify, sell and distribute this document
+ is granted provided this copyright notice appears in all copies. This document
+ is provided "as is" without express or implied warranty, and with
+ no claim as to its suitability for any purpose.
@@ -21,7 +21,7 @@

- 
+ 


- 
+ 

diff --git a/doc/tutorial/doc/class_operators_special_functions.html b/doc/tutorial/doc/class_operators_special_functions.html
index e22bd2ff..ce7aab66 100644
--- a/doc/tutorial/doc/class_operators_special_functions.html
+++ b/doc/tutorial/doc/class_operators_special_functions.html
@@ -3,7 +3,7 @@
@@ -95,7 +95,7 @@ Well, the method str requires the operator<< to do its w
- 
+ 


diff --git a/doc/tutorial/doc/class_virtual_functions.html b/doc/tutorial/doc/class_virtual_functions.html
index 46cb7837..37ce60ce 100644
--- a/doc/tutorial/doc/class_virtual_functions.html
+++ b/doc/tutorial/doc/class_virtual_functions.html
@@ -4,7 +4,7 @@
- 
+ 


@@ -21,7 +21,7 @@

- 
+ 

-Now, at last, we can even derive from our base class Base in Python. Before -we can do that, we have to set up our class_ wrapper as:
-
- class_<Base, BaseWrap, boost::noncopyable>("Base")
- ;
-
--Otherwise, we have to suppress the Base class' no_init by adding an -__init__() method to all our derived classes. no_init actually adds -an __init__ method that raises a Python RuntimeError exception.
-
- >>> class Derived(Base):
- ... def f(self):
- ... return 42
- ...
-
--Cool eh? A Python class deriving from a C++ class!
--Let's now make an instance of our Python class Derived:
-
- >>> derived = Derived()
-
--Calling derived.f():
-
- >>> derived.f()
- 42
-
--Will yield the expected result. Finally, calling calling the free function -call_f with derived as argument:
-
- >>> call_f(derived)
- 42
-
--Will also yield the expected result.
--Here's what's happening:
--Rewind back to our Base class, if its member function f was not -declared as pure virtual:
-
- struct Base
- {
- virtual int f() { return 0; }
- };
-
--And instead is implemented to return 0, as shown above.
-
- struct BaseWrap : Base
- {
- BaseWrap(PyObject* self_)
- : self(self_) {}
- int f() { return call_method<int>(self, "f"); }
- static int default_f(Base* b) { return b->Base::f(); } // <<=== added
- PyObject* self;
- };
-
--then, our Boost.Python wrapper:
-
- class_<Base, BaseWrap>("Base")
- .def("f", &BaseWrap::default_f)
- ;
-
--Note that we are allowing Base objects to be instantiated this time, -unlike before where we specifically defined the class_<Base> with -no_init.
--In Python, the results would be as expected:
-
- >>> base = Base()
- >>> class Derived(Base):
- ... def f(self):
- ... return 42
- ...
- >>> derived = Derived()
-
--Calling base.f():
-
- >>> base.f()
- 0
-
--Calling derived.f():
-
- >>> derived.f()
- 42
-
--Calling call_f, passing in a base object:
-
- >>> call_f(base)
- 0
-
--Calling call_f, passing in a derived object:
-
- >>> call_f(derived)
- 42
-
![]() |
![]() |
- ![]() |
+ ![]() |
![]() |
- ![]() |
- ![]() |
+ ![]() |
+ ![]() |
@@ -44,8 +44,10 @@ to retrieve the default arguments:
def("f", f); // defaults lost!-Because of this, when wrapping C++ code in earlier versions of -Boost.Python, we had to resort to writing thin wrappers:
+Because of this, when wrapping C++ code, we had to resort to manual +wrapping as outlined in the +previous section, or +writing thin wrappers:
// write "thin wrappers"
int f1(int x) { f(x); }
@@ -142,8 +144,8 @@ Notice the use of init<...> and optional<...> to s

- 
- 
+ 
+ 
diff --git a/doc/tutorial/doc/deriving_a_python_class.html b/doc/tutorial/doc/deriving_a_python_class.html
new file mode 100644
index 00000000..d5a8034e
--- /dev/null
+++ b/doc/tutorial/doc/deriving_a_python_class.html
@@ -0,0 +1,82 @@
+
+
+
+Deriving a Python Class
+
+
+
+
+
+
+
+
+
+
+ Deriving a Python Class
+
+
+
+
+
+
+ 
+ 
+ 
+
+
+
+Continuing, now, at last, we can even derive from our base class Base in
+Python. Before we can do that, we have to set up our class_ wrapper as:
+
+ class_<Base, BaseWrap, boost::noncopyable>("Base")
+ ;
+
+
+Otherwise, we have to suppress the Base class' no_init by adding an
+__init__() method to all our derived classes. no_init actually adds
+an __init__ method that raises a Python RuntimeError exception.
+
+ >>> class Derived(Base):
+ ... def f(self):
+ ... return 42
+ ...
+
+
+Cool eh? A Python class deriving from a C++ class!
+
+Let's now make an instance of our Python class Derived:
+
+ >>> derived = Derived()
+
+
+Calling derived.f():
+
+ >>> derived.f()
+ 42
+
+
+Will yield the expected result. Finally, calling calling the free function
+call_f with derived as argument:
+
+ >>> call_f(derived)
+ 42
+
+
+Will also yield the expected result.
+
+Here's what's happening:
+- 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.
- call_method<int>(self, "f"); dispatches the call back to Python.
- def f(self): return 42 is finally called.
+
+ 
+ 
+ 
+
+
+
+
Copyright © 2002-2003 David Abrahams
Copyright © 2002-2003 Joel de Guzman
+Permission to copy, use, modify, sell and distribute this document
+ is granted provided this copyright notice appears in all copies. This document
+ is provided "as is" without express or implied warranty, and with
+ no claim as to its suitability for any purpose.
+
+
diff --git a/doc/tutorial/doc/object_interface.html b/doc/tutorial/doc/object_interface.html
index 1fd3a04d..1988dcd7 100644
--- a/doc/tutorial/doc/object_interface.html
+++ b/doc/tutorial/doc/object_interface.html
@@ -3,7 +3,7 @@
Object Interface
-
+
@@ -20,7 +20,7 @@

- 
+ 

@@ -40,7 +40,7 @@ should minimize the learning curve significantly.

- 
+ 

diff --git a/doc/tutorial/doc/overloading.html b/doc/tutorial/doc/overloading.html
index da0ad8ac..06baaa3a 100644
--- a/doc/tutorial/doc/overloading.html
+++ b/doc/tutorial/doc/overloading.html
@@ -3,8 +3,8 @@
Overloading
-
-
+
+
@@ -20,59 +20,16 @@

- 
- 
+ 
+ 
-It was mentioned in passing in the previous section that
-BOOST_PYTHON_FUNCTION_OVERLOADS and BOOST_PYTHON_FUNCTION_OVERLOADS
-can also be used for overloaded functions and member functions with a
-common sequence of initial arguments. Here is an example:
-
- void foo()
- {
- /*...*/
- }
-
- void foo(bool a)
- {
- /*...*/
- }
-
- void foo(bool a, int b)
- {
- /*...*/
- }
-
- void foo(bool a, int b, char c)
- {
- /*...*/
- }
-
-
-Like in the previous section, we can generate thin wrappers for these
-overloaded functions in one-shot:
-
- BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
-
-
-Then...
-
- .def("foo", foo, foo_overloads());
-
-
-Notice though that we have a situation now where we have a minimum of zero
-(0) arguments and a maximum of 3 arguments.
-Manual Wrapping
-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.
-
-The following illustrates an alternate scheme for manually wrapping an
-overloaded member function instead of
-BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS. Obviously, the same technique
-can be applied to wrapping overloaded non- member functions.
+The following illustrates a scheme for manually wrapping an overloaded
+member function or. Obviously, the same technique can be applied to
+wrapping overloaded non- member functions. Take note that this scheme
+applies to actual overloaded (member, non-member) functions as well as
+(member, non-member) functions with default arguments.
We have here our C++ classes:
@@ -113,33 +70,11 @@ With these in hand, we can proceed to define and wrap this for Python:
.def("f", fx3)
.def("f", fx4)
-
-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. Since the first overload
-has default arguments, we can use BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
-to automatically wrap the first three of the defs above and manually
-wrap just the last. Here's how we'll do this:
-
- BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
-
-
-Create a member function pointers as above for both X::f overloads:
-
- bool (X::*fx1)(int, double, char) = &X::f;
- int (X::*fx2)(int, int, int) = &X::f;
-
-
-Then...
-
- .def("f", fx1, xf_overloads());
- .def("f", fx2)
-

- 
- 
+ 
+ 
diff --git a/doc/tutorial/doc/quickstart.txt b/doc/tutorial/doc/quickstart.txt
index 3d4eb7ec..a071949a 100644
--- a/doc/tutorial/doc/quickstart.txt
+++ b/doc/tutorial/doc/quickstart.txt
@@ -527,10 +527,10 @@ Why is it an error? [^Base] is an abstract class. As such it is advisable
to define the Python wrapper with [^no_init] as we have done above. Doing
so will disallow abstract base classes such as [^Base] to be instantiated.
-[h2 Deriving a Python class]
+[page:1 Deriving a Python Class]
-Now, at last, we can even derive from our base class Base in Python. Before
-we can do that, we have to set up our class_ wrapper as:
+Continuing, now, at last, we can even derive from our base class Base in
+Python. Before we can do that, we have to set up our [^class_] wrapper as:
class_ ("Base")
;
@@ -572,30 +572,45 @@ Here's what's happening:
# [^call_method(self, "f");] dispatches the call back to Python.
# [^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:
+[page:1 Virtual Functions with Default Implementations]
+
+Recall that in the [@class_virtual_functions.html 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:
+
+ struct Base
+ {
+ virtual int f() = 0;
+ };
+
+had a pure virtual function [^f]. If, however, its member function [^f] was
+not declared as pure virtual:
struct Base
{
virtual int f() { return 0; }
};
-And instead is implemented to return [^0], as shown above.
+and instead had a default implementation that returns [^0], as shown above,
+we need to add a forwarding function that calls the [^Base] default virtual
+function [^f] implementation:
struct BaseWrap : Base
{
BaseWrap(PyObject* self_)
: self(self_) {}
int f() { return call_method(self, "f"); }
- static int default_f(Base* b) { return b->Base::f(); } // <<=== added
+ int default_f() { return Base::f(); } // <<=== ***ADDED***
PyObject* self;
};
-then, our Boost.Python wrapper:
+Then, 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. Here's how it is
+applied to our example above:
class_ ("Base")
- .def("f", &BaseWrap::default_f)
- ;
+ .def("f", &Base::f, &BaseWrap::default_f)
Note that we are allowing [^Base] objects to be instantiated this time,
unlike before where we specifically defined the [^class_ ] with
@@ -874,6 +889,51 @@ these can be found [@../../v2/reference.html#models_of_call_policies here].
"Explicit is better than implicit"[br]
"In the face of ambiguity, refuse the temptation to guess"[br]]
+[page:1 Overloading]
+
+The following illustrates a scheme for manually wrapping an overloaded
+member function or. Obviously, the same technique can be applied to
+wrapping overloaded non- member functions. Take note that this scheme
+applies to actual overloaded (member, non-member) functions as well as
+(member, non-member) functions with default arguments.
+
+We have here our C++ classes:
+
+ struct X
+ {
+ bool f(int a, double b = 0, char c = 'x')
+ {
+ return true;
+ }
+
+ int f(int a, int b, int c)
+ {
+ return a + b + c;
+ };
+ };
+
+Notice that class X has two overloaded functions with different signatures.
+The types of the arguments, and the return are totally different, unlike
+above where we have a common sequence of initial arguments.
+
+We shall start by introducing some member function pointer variables:
+
+ bool (X::*fx1)(int) = &X::f;
+ bool (X::*fx2)(int, double) = &X::f;
+ bool (X::*fx3)(int, double, char)= &X::f;
+ int (X::*fx4)(int, int, int) = &X::f;
+
+The first three member function pointers take care of the first X::f
+overload. The one with default arguments. The last member function pointer
+takes care of the second X::f overload.
+
+With these in hand, we can proceed to define and wrap this for Python:
+
+ .def("f", fx1)
+ .def("f", fx2)
+ .def("f", fx3)
+ .def("f", fx4)
+
[page:1 Default Arguments]
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
@@ -892,8 +952,9 @@ to retrieve the default arguments:
def("f", f); // defaults lost!
-Because of this, when wrapping C++ code in earlier versions of
-Boost.Python, we had to resort to writing thin wrappers:
+Because of this, when wrapping C++ code, we had to resort to manual
+wrapping as outlined in the [@overloading.html previous section], or
+writing thin wrappers:
// write "thin wrappers"
int f1(int x) { f(x); }
@@ -987,7 +1048,7 @@ You can easily add this constructor to Boost.Python in one shot:
Notice the use of [^init<...>] and [^optional<...>] to signify the default
(optional arguments).
-[page:1 Overloading]
+[page:1 Auto-Overloading]
It was mentioned in passing in the previous section that
[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_FUNCTION_OVERLOADS]
@@ -1030,56 +1091,17 @@ Notice though that we have a situation now where we have a minimum of zero
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.
-
-The following illustrates an alternate scheme for manually wrapping an
-overloaded member function instead of
-[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]. Obviously, the same technique
-can be applied to wrapping overloaded non- member functions.
-
-We have here our C++ classes:
-
- struct X
- {
- bool f(int a, double b = 0, char c = 'x')
- {
- return true;
- }
-
- int f(int a, int b, int c)
- {
- return a + b + c;
- };
- };
-
-Notice that class X has two overloaded functions with different signatures.
-The types of the arguments, and the return are totally different, unlike
-above where we have a common sequence of initial arguments.
-
-We shall start by introducing some member function pointer variables:
-
- bool (X::*fx1)(int) = &X::f;
- bool (X::*fx2)(int, double) = &X::f;
- bool (X::*fx3)(int, double, char)= &X::f;
- int (X::*fx4)(int, int, int) = &X::f;
-
-The first three member function pointers take care of the first X::f
-overload. The one with default arguments. The last member function pointer
-takes care of the second X::f overload.
-
-With these in hand, we can proceed to define and wrap this for Python:
-
- .def("f", fx1)
- .def("f", fx2)
- .def("f", fx3)
- .def("f", fx4)
+will not work. If this is not the case, we have to wrap our functions
+[@overloading.html 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]. Since the first overload
-has default arguments, we can use [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
-to automatically wrap the first three of the [^def]s above and manually
-wrap just the last. Here's how we'll do this:
+its sister, [^BOOST_PYTHON_FUNCTION_OVERLOADS]. Following up on our example
+presented in the section [@overloading.html on overloading], since the
+first overload has default arguments, we can use
+[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] to automatically wrap the first
+three of the [^def]s above and manually wrap just the last. Here's how
+we'll do this:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(xf_overloads, f, 1, 4)
diff --git a/doc/tutorial/doc/virtual_functions_with_default_implementations.html b/doc/tutorial/doc/virtual_functions_with_default_implementations.html
new file mode 100644
index 00000000..f7b15115
--- /dev/null
+++ b/doc/tutorial/doc/virtual_functions_with_default_implementations.html
@@ -0,0 +1,122 @@
+
+
+
+Virtual Functions with Default Implementations
+
+
+
+
+
+
+
+
+
+
+ Virtual Functions with Default Implementations
+
+
+
+
+
+
+ 
+ 
+ 
+
+
+
+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:
+
+ struct Base
+ {
+ virtual int f() = 0;
+ };
+
+
+had a pure virtual function f. If, however, its member function f was
+not declared as pure virtual:
+
+ struct Base
+ {
+ virtual int f() { return 0; }
+ };
+
+
+and instead had a default implementation that returns 0, as shown above,
+we need to add a forwarding function that calls the Base default virtual
+function f implementation:
+
+ struct BaseWrap : Base
+ {
+ BaseWrap(PyObject* self_)
+ : self(self_) {}
+ int f() { return call_method<int>(self, "f"); }
+ int default_f() { return Base::f(); } // <<=== ***ADDED***
+ PyObject* self;
+ };
+
+
+Then, 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. Here's how it is
+applied to our example above:
+
+ class_<Base, BaseWrap>("Base")
+ .def("f", &Base::f, &BaseWrap::default_f)
+
+
+Note that we are allowing Base objects to be instantiated this time,
+unlike before where we specifically defined the class_<Base> with
+no_init.
+
+In Python, the results would be as expected:
+
+ >>> base = Base()
+ >>> class Derived(Base):
+ ... def f(self):
+ ... return 42
+ ...
+ >>> derived = Derived()
+
+
+Calling base.f():
+
+ >>> base.f()
+ 0
+
+
+Calling derived.f():
+
+ >>> derived.f()
+ 42
+
+
+Calling call_f, passing in a base object:
+
+ >>> call_f(base)
+ 0
+
+
+Calling call_f, passing in a derived object:
+
+ >>> call_f(derived)
+ 42
+
+
+
+ 
+ 
+ 
+
+
+
+
Copyright © 2002-2003 David Abrahams
Copyright © 2002-2003 Joel de Guzman
+Permission to copy, use, modify, sell and distribute this document
+ is granted provided this copyright notice appears in all copies. This document
+ is provided "as is" without express or implied warranty, and with
+ no claim as to its suitability for any purpose.
+
+
diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html
index 108d25f6..9439b300 100644
--- a/doc/tutorial/index.html
+++ b/doc/tutorial/index.html
@@ -60,6 +60,16 @@
Class Virtual Functions
+
+
+ Deriving a Python Class
+
+
+
+
+ Virtual Functions with Default Implementations
+
+
Class Operators/Special Functions
@@ -75,6 +85,11 @@
Call Policies
+
+
+ Overloading
+
+
Default Arguments
@@ -82,7 +97,7 @@
- Overloading
+ Auto-Overloading