mirror of
https://github.com/boostorg/python.git
synced 2026-01-29 19:52:16 +00:00
Documentation update
[SVN r8326]
This commit is contained in:
@@ -34,9 +34,9 @@
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. 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.
|
||||
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.
|
||||
<p>
|
||||
Updated: Oct 30, 2000
|
||||
</div>
|
||||
|
||||
@@ -17,28 +17,33 @@
|
||||
it relieves the user from worrying about reference-counts. As far as I
|
||||
can tell, there is no support for subclassing C++ extension types in
|
||||
Python. An even more-significant difference is that a user's C++ code is
|
||||
still basically "dealing with Python objects", though they are wrapped
|
||||
still basically “dealing with Python objects”, though they are wrapped
|
||||
in C++ classes. This means such jobs as argument parsing and conversion
|
||||
are still left to be done explicitly by the user. This is not entirely a
|
||||
bad thing, as you can do some Pythonic things with CXX (e.g. variable
|
||||
and keyword arguments) that I haven't yet figured out how to enable with
|
||||
py_cpp.
|
||||
<p>
|
||||
As far as I can tell, CXX enables one to write what is essentially
|
||||
idiomatic Python code in C++, manipulating Python objects through the
|
||||
same fully-generic interfaces we use in Python. That use is also
|
||||
supported by the py_cpp object wrappers. CXX claims to interoperate well
|
||||
with the C++ Standard Library (a.k.a. STL) by providing iterators into
|
||||
Python Lists and Dictionaries, but the claim is unfortunately
|
||||
unsupportable. The problem is that in general, access to Python sequence and
|
||||
mapping elements through iterators requires the use of proxy objects as
|
||||
the return value of iterator dereference operations. This usage
|
||||
conflicts with the basic ForwardIterator requirements in <a
|
||||
are still left to be done explicitly by the user.
|
||||
|
||||
<p>
|
||||
CXX claims to interoperate well with the C++ Standard Library
|
||||
(a.k.a. STL) by providing iterators into Python Lists and Dictionaries,
|
||||
but the claim is unfortunately unsupportable. The problem is that in
|
||||
general, access to Python sequence and mapping elements through
|
||||
iterators requires the use of proxy objects as the return value of
|
||||
iterator dereference operations. This usage conflicts with the basic
|
||||
ForwardIterator requirements in <a
|
||||
href="http://anubis.dkuug.dk/jtc1/sc22/open/n2356/lib-iterators.html#lib.forward.iterators">
|
||||
section 24.1.3 of the standard</a> (dereferencing must produce a
|
||||
reference). Although you may be able to use these iterators with some
|
||||
operations in some standard library implementations, it is neither
|
||||
guaranteed to work nor portable.
|
||||
|
||||
<p>
|
||||
As far as I can tell, CXX enables one to write what is essentially
|
||||
idiomatic Python code in C++, manipulating Python objects through the
|
||||
same fully-generic interfaces we use in Python. I think it would be fair
|
||||
to say that while you're not programming directly to the “bare
|
||||
metal” with CXX, in comparison to py_cpp, it presents a low-level
|
||||
interface to Python. That use is also supported by the py_cpp object
|
||||
wrappers.
|
||||
|
||||
<p>
|
||||
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
||||
author of CXX, has told me that what I've described is only half of the
|
||||
@@ -46,11 +51,11 @@
|
||||
fill in the other half. Here is his response to the commentary above:
|
||||
|
||||
<blockquote>
|
||||
"My intention with CXX was not to do what you are doing. It was to enable a
|
||||
“My intention with CXX was not to do what you are doing. It was to enable a
|
||||
person to write an extension directly in C++ rather than C. I figured others had
|
||||
the wrapping business covered. I thought maybe CXX would provide an easier
|
||||
target language for those making wrappers, but I never explored
|
||||
that."<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
that.”<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
</blockquote>
|
||||
|
||||
<h2>SWIG</h2>
|
||||
@@ -62,20 +67,20 @@ that."<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
Perl or Tcl) extension module. It has been successfully used to create
|
||||
many Python extension modules. Like py_cpp, SWIG is trying to allow an
|
||||
existing interface to be wrapped with little or no change to the
|
||||
existing code. The documentation says "SWIG parses a form of ANSI C
|
||||
existing code. The documentation says “SWIG parses a form of ANSI C
|
||||
syntax that has been extended with a number of special directives. As a
|
||||
result, interfaces are usually built by grabbing a header file and
|
||||
tweaking it a little bit." For C++ interfaces, the tweaking has often
|
||||
tweaking it a little bit.” For C++ interfaces, the tweaking has often
|
||||
proven to amount to more than just a little bit. One user
|
||||
writes:
|
||||
|
||||
<blockquote> "The problem with swig (when I used it) is that it
|
||||
<blockquote> “The problem with swig (when I used it) is that it
|
||||
couldnt handle templates, didnt do func overloading properly etc. For
|
||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
||||
problem. Simple things work. But for anything very complicated (or
|
||||
realistic), one had to write code by hand. I believe py_cpp doesn't have
|
||||
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
||||
wrap correctly."<br><i>-Prabhu Ramachandran</i>
|
||||
wrap correctly.”<br><i>-Prabhu Ramachandran</i>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
@@ -119,7 +124,7 @@ that."<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
<a
|
||||
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
||||
is another very ambitious project aimed at generating Python wrappers for
|
||||
interfaces written in "legacy languages", among which C++ is the first one
|
||||
interfaces written in “legacy languages”, among which C++ is the first one
|
||||
implemented. Like SWIG, it aims to parse source code and automatically
|
||||
generate wrappers, though it appears to take a more sophisticated approach
|
||||
to parsing in general and C++ in particular, so it should do a much better
|
||||
@@ -145,9 +150,11 @@ an inheritance relationship?
|
||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as py_cpp
|
||||
to support subclassing of extension types in Python, including
|
||||
multiple-inheritance. Both systems rely on the same "<a
|
||||
multiple-inheritance. Both systems support pickling/unpickling of
|
||||
extension class instances in very similar ways. Both systems rely on the
|
||||
same “<a
|
||||
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
||||
Beaudry Hack</a>" that also inspired Don's MESS System.
|
||||
Beaudry Hack</a>” that also inspired Don's MESS System.
|
||||
<p>
|
||||
The major differences are:
|
||||
<ul>
|
||||
@@ -170,30 +177,27 @@ an inheritance relationship?
|
||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
||||
Zope Example</a> illustrates the differences.
|
||||
<li>
|
||||
Zope's ExtensionClasses are specifically motivated by "the need for a
|
||||
C-based persistence mechanism". Py_cpp's are motivated by the desire
|
||||
Zope's ExtensionClasses are specifically motivated by “the need for a
|
||||
C-based persistence mechanism”. Py_cpp's are motivated by the desire
|
||||
to simply reflect a C++ API into Python with as little modification as
|
||||
possible.
|
||||
<li>
|
||||
Thus, Zope's ExtensionClasses support pickling. Currently py_cpp
|
||||
ExtensionClasses do not.
|
||||
<li>
|
||||
The following Zope restriction does not apply to py_cpp: "At most one
|
||||
The following Zope restriction does not apply to py_cpp: “At most one
|
||||
base extension direct or indirect super class may define C data
|
||||
members. If an extension subclass inherits from multiple base
|
||||
extension classes, then all but one must be mix-in classes that
|
||||
provide extension methods but no data."
|
||||
provide extension methods but no data.”
|
||||
<li>
|
||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
||||
"inheritedAttribute" on <a
|
||||
“inheritedAttribute” on <a
|
||||
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
||||
method to access base class methods. In py_cpp, base class methods can
|
||||
be accessed in the usual way by writing
|
||||
"<code>BaseClass.method</code>".
|
||||
“<code>BaseClass.method</code>”.
|
||||
<li>
|
||||
Zope supplies some creative but esoteric idioms such as <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
||||
Acquisition</a>.
|
||||
Acquisition</a>. No specific support for this is built into py_cpp.
|
||||
<li>
|
||||
Zope's ComputedAttribute support is designed to be used from Python.
|
||||
<a href="special.html#getter_setter">The analogous feature of
|
||||
@@ -207,10 +211,10 @@ an inheritance relationship?
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. 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
|
||||
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.
|
||||
<p>
|
||||
Updated: Oct 30, 2000
|
||||
Updated: Nov 25, 2000
|
||||
</div>
|
||||
|
||||
|
||||
@@ -85,9 +85,9 @@ my_class.add(python::to_python(enum_value_2), "enum_value_2");
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. 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.
|
||||
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.
|
||||
<p>
|
||||
Updated: Nov 12, 2000
|
||||
</div>
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <string>
|
||||
|
||||
namespace hello {
|
||||
class world
|
||||
{
|
||||
public:
|
||||
world(int);
|
||||
~world();
|
||||
const char* get() const { return "hi, world"; }
|
||||
std::string get() const { return "hi, world"; }
|
||||
...
|
||||
};
|
||||
std::size_t length(const world& x) { return std::strlen(x.get()); }
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace scope as Python member functions.
|
||||
class is found which has a matching attribute, only functions overloaded
|
||||
in the context of that class are candidates for overload resolution. In
|
||||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
||||
in a derived class "hides" all functions with the same name from a base
|
||||
in a derived class “hides” all functions with the same name from a base
|
||||
class.
|
||||
<p>
|
||||
|
||||
@@ -132,13 +132,12 @@ namespace scope as Python member functions.
|
||||
functions are tried in the same order they were
|
||||
<code>def()</code>ed. The first function whose signature can be made to
|
||||
match each argument passed is the one which is ultimately called.
|
||||
<br>
|
||||
This means in particular that you cannot overload the same function on
|
||||
both "<code>int</code>" and "<code>float</code>" because Python
|
||||
both “<code>int</code>” and “<code>float</code>” because Python
|
||||
automatically converts either of the two types into the other one.
|
||||
Thus, if the "<code>float</code>"-overload is found first, it is used
|
||||
also used for arguments of type "<code>int</code>" as well, and the
|
||||
"<code>int</code>"-Version of the function is never invoked.
|
||||
If the “<code>float</code>” overload is found first, it is used
|
||||
also used for arguments of type “<code>int</code>” as well, and the
|
||||
“<code>int</code>” version of the function is never invoked.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
@@ -148,9 +147,9 @@ namespace scope as Python member functions.
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. 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.
|
||||
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.
|
||||
<p>
|
||||
Updated: Nov 21, 2000
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
In the <a href="example1.html">previous example</a> we exposed a simple
|
||||
C++ class in Python and showed that we could write a subclass. We even
|
||||
redefined one of the functions in our derived class. Now we will learn
|
||||
how to make the function <em>behave virtually</em>.
|
||||
how to make the function behave virtually <em>when called from C++</em>.
|
||||
|
||||
|
||||
<h2><a name="overriding_example">Example</a></h2>
|
||||
@@ -26,7 +26,7 @@ class world
|
||||
public:
|
||||
world(int);
|
||||
virtual ~world();
|
||||
<b>virtual</b> const char* get() const { return "hi, world"; }
|
||||
<b>virtual</b> std::string get() const { return "hi, world"; }
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
@@ -37,23 +37,24 @@ class world
|
||||
|
||||
<ol>
|
||||
|
||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member that holds a reference to the
|
||||
corresponding Python object.
|
||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member that holds a
|
||||
reference to the corresponding Python object.
|
||||
|
||||
<li><a name="derived_2">A</a> constructor for each exposed constructor of the base class which stores an
|
||||
additional initial <code>PyObject*</code> argument in the data
|
||||
member described above.
|
||||
<li><a name="derived_2">A</a> constructor for each exposed constructor of the
|
||||
base class which stores an additional initial <code>PyObject*</code> argument
|
||||
in the data member described above.
|
||||
|
||||
<li><a name="derived_3">An</a> implementation of each virtual function you may wish to override in
|
||||
Python which uses
|
||||
<code>python::callback<<i>return-type</i>>::call_method()</code> to call the
|
||||
Python override.
|
||||
<li><a name="derived_3">An</a> implementation of each virtual function you may
|
||||
wish to override in Python which uses
|
||||
<code>python::callback<<i>return-type</i>>::call_method()</code> to call
|
||||
the Python override.
|
||||
|
||||
<li><a name="derived_4">For</a> each non-pure virtual function meant to be overridable from Python, a
|
||||
static member function (or a free function) taking a reference or pointer to the
|
||||
base type as the first parameter and which forwards any additional parameters
|
||||
neccessary to the <i>default</i> implementation of the virtual function. See also
|
||||
<a href="#private">this note</a> if the base class virtual function is private.
|
||||
<li><a name="derived_4">For</a> each non-pure virtual function meant to be
|
||||
overridable from Python, a static member function (or a free function) taking
|
||||
a reference or pointer to the base type as the first parameter and which
|
||||
forwards any additional parameters neccessary to the <i>default</i>
|
||||
implementation of the virtual function. See also <a href="#private">this
|
||||
note</a> if the base class virtual function is private.
|
||||
|
||||
</ol>
|
||||
|
||||
@@ -64,10 +65,10 @@ struct world_callback : world
|
||||
: world(x),
|
||||
m_self(self) {}
|
||||
|
||||
const char* get() const // <a href="#derived_3">3</a>
|
||||
{ return python::callback<const char*>::call_method(m_self, "get"); }
|
||||
std::string get() const // <a href="#derived_3">3</a>
|
||||
{ return python::callback<std::string>::call_method(m_self, "get"); }
|
||||
|
||||
static const char* <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
|
||||
static std::string <a name= "default_implementation">default_get</a>(const hello::world& self) const // <a href="#derived_4">4</a>
|
||||
{ return self.world::get(); }
|
||||
private:
|
||||
PyObject* m_self; // <a href="#derived_1">1</a>
|
||||
@@ -112,15 +113,15 @@ world_class.def(&world::get, "get", &<b>world_callback::default_get</b>)
|
||||
<h2>Pure Virtual Functions</h2>
|
||||
|
||||
<p>
|
||||
A pure virtual function with no implementation is actually a lot easier
|
||||
to deal with than a virtual function with a default implementation. First
|
||||
of all, you obviously don't need to <a href="#default_implementation">
|
||||
supply a default implementation</a>. Secondly, you don't need to call
|
||||
A pure virtual function with no implementation is actually a lot easier to
|
||||
deal with than a virtual function with a default implementation. First of
|
||||
all, you obviously don't need to <a href="#default_implementation"> supply
|
||||
a default implementation</a>. Secondly, you don't need to call
|
||||
<code>def()</code> on the <code>extension_class<></code> instance
|
||||
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
||||
corresponding attribute on the Python class stays undefined, you'll get
|
||||
an <code>AttributeError</code> in Python when you try to call the
|
||||
function, indicating that it should have been implemented. For example:
|
||||
corresponding attribute on the Python class stays undefined, you'll get an
|
||||
<code>AttributeError</code> in Python when you try to call the function,
|
||||
indicating that it should have been implemented. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
struct baz {
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="c++boost.gif" alt= "c++boost.gif (8819 bytes)">Pointers
|
||||
</h1>
|
||||
<h2>The Problem With Pointers</h2>
|
||||
|
||||
<h2><a name="problem">The Problem With Pointers</a></h2>
|
||||
|
||||
<p>
|
||||
In general, raw pointers passed to or returned from functions are problematic
|
||||
for py_cpp because pointers have too many potential meanings. Is it an iterator?
|
||||
@@ -32,10 +34,10 @@ converted from/to Python strings.
|
||||
<h3>Can you avoid the problem?</h3>
|
||||
|
||||
<p>My first piece of advice to anyone with a case not covered above is
|
||||
"find a way to avoid the problem." For example, if you have just one
|
||||
“find a way to avoid the problem.” For example, if you have just one
|
||||
or two functions returning a pointer to a single (not an array of) <code>const
|
||||
T*</code> for some wrapped <code>T</code>, you may be able to write a "thin
|
||||
converting wrapper" over those two functions as follows (Since py_cpp
|
||||
T*</code> for some wrapped <code>T</code>, you may be able to write a “thin
|
||||
converting wrapper” over those two functions as follows (Since py_cpp
|
||||
converts <code>const T&</code> values <code>to_python</code> by copying the T
|
||||
into a new extension instance, Foo must have a public copy constructor):
|
||||
|
||||
|
||||
19
py_cpp.html
19
py_cpp.html
@@ -20,8 +20,16 @@
|
||||
very similar to the C++ interface. It is designed to be minimally
|
||||
intrusive on your C++ design. In most cases, you should not have to alter
|
||||
your C++ classes in any way in order to use them with py_cpp. The system
|
||||
<em>should</em> simply "reflect" your C++ classes and functions into
|
||||
Python.
|
||||
<em>should</em> simply “reflect” your C++ classes and functions into
|
||||
Python. The major features of py_cpp include support for:
|
||||
<ul>
|
||||
<li><a href="inheritance.hml">Subclassing extension types in Python</a>
|
||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
||||
</ul>
|
||||
among others.
|
||||
|
||||
|
||||
<h2>Supported Platforms</h2>
|
||||
<p>py_cpp has been tested in the following configurations:
|
||||
@@ -60,12 +68,11 @@
|
||||
</ul>
|
||||
|
||||
<p>Py_cpp requires the <a href="http://www.boost.org">boost</a> libraries, and is
|
||||
has been accepted for inclusion into the boost libraries pending "boostification"
|
||||
has been accepted for inclusion into the boost libraries pending “boostification“
|
||||
(completion of the documentation, change in some naming conventions and
|
||||
resolution of some namespace issues).
|
||||
|
||||
<h2>Credits</h2>
|
||||
<p>
|
||||
<ul>
|
||||
<li><a href="mailto:abrahams@mediaone.net">David Abrahams</a> originated
|
||||
and wrote py_cpp.
|
||||
@@ -196,9 +203,9 @@
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. 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
|
||||
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.
|
||||
<p>
|
||||
Updated: Nov 21, 2000
|
||||
Updated: Nov 25, 2000
|
||||
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
A Peek Under the Hood
|
||||
</h1>
|
||||
<p>
|
||||
<code> extension_class<T></code> is a subclass of <code>
|
||||
Declaring a <code>class_builder<T></code> causes the instantiation
|
||||
of an <code>extension_class<T></code> to which it forwards all
|
||||
member function calls and which is doing most of the real work.
|
||||
<code>extension_class<T></code> is a subclass of <code>
|
||||
PyTypeObject</code>, the <code> struct</code> which Python's 'C' API uses
|
||||
to describe a type. <a href="example1.html#world_class">An obj of
|
||||
the <code>extension_class<></code></a> becomes the Python type
|
||||
object corresponding to <code>hello::world</code>. When we <a href=
|
||||
to describe a type. <a href="example1.html#world_class">An instance of the
|
||||
<code>extension_class<></code></a> becomes the Python type object
|
||||
corresponding to <code>hello::world</code>. When we <a href=
|
||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
||||
module's dictionary to be looked up under the name "world".
|
||||
<p>
|
||||
@@ -45,8 +48,8 @@
|
||||
the top of your module's init function, then <code>def</code> the member
|
||||
functions later to avoid problems with inter-class dependencies.
|
||||
<p>
|
||||
Previous: <a href="overriding.html">function Overloading</a>
|
||||
Next: <a href="building.html">Building a module_builder with Py_cpp</a>
|
||||
Previous: <a href="overriding.html">Function Overloading</a>
|
||||
Next: <a href="building.html">Building a Module with Py_cpp</a>
|
||||
Up: <a href="py_cpp.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
|
||||
Reference in New Issue
Block a user