2
0
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:
Dave Abrahams
2000-11-25 23:23:48 +00:00
parent e668f3ce56
commit 3cf34f9e3d
9 changed files with 113 additions and 95 deletions

View File

@@ -34,9 +34,9 @@
<p>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Oct 30, 2000
</div>

View File

@@ -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 &ldquo;dealing with Python objects&rdquo;, 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 &ldquo;bare
metal&rdquo; 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
&ldquo;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.&rdquo;<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 &ldquo;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.&rdquo; 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> &ldquo;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.&rdquo;<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 &ldquo;legacy languages&rdquo;, 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 &ldquo;<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>&rdquo; 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 &ldquo;the need for a
C-based persistence mechanism&rdquo;. 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: &ldquo;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.&rdquo;
<li>
Zope requires use of the somewhat funky inheritedAttribute (search for
"inheritedAttribute" on <a
&ldquo;inheritedAttribute&rdquo; 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>".
&ldquo;<code>BaseClass.method</code>&rdquo;.
<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>
&copy; 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 &ldquo;as is&rdquo; 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>

View File

@@ -85,9 +85,9 @@ my_class.add(python::to_python(enum_value_2), "enum_value_2");
<p>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Nov 12, 2000
</div>

View File

@@ -16,13 +16,15 @@
Python:
<blockquote>
<pre>
#include &lt;string&gt;
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&amp; x) { return std::strlen(x.get()); }

View File

@@ -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 &ldquo;hides&rdquo; 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 &ldquo;<code>int</code>&rdquo; and &ldquo;<code>float</code>&rdquo; 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 &ldquo;<code>float</code>&rdquo; overload is found first, it is used
also used for arguments of type &ldquo;<code>int</code>&rdquo; as well, and the
&ldquo;<code>int</code>&rdquo; version of the function is never invoked.
</ul>
<p>
@@ -148,9 +147,9 @@ namespace scope as Python member functions.
<p>
&copy; 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 &ldquo;as
is&rdquo; without express or implied warranty, and with no claim as to
its suitability for any purpose.
<p>
Updated: Nov 21, 2000
</div>

View File

@@ -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&lt<i>return-type</i>&gt;::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&lt<i>return-type</i>&gt;::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&lt;const char*&gt;::call_method(m_self, "get"); }
std::string get() const // <a href="#derived_3">3</a>
{ return python::callback&lt;std::string&gt;::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(&amp;world::get, "get", &amp;<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&lt;&gt;</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 {

View File

@@ -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
&quot;find a way to avoid the problem.&quot; For example, if you have just one
&ldquo;find a way to avoid the problem.&rdquo; 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 &quot;thin
converting wrapper&quot; over those two functions as follows (Since py_cpp
T*</code> for some wrapped <code>T</code>, you may be able to write a &ldquo;thin
converting wrapper&rdquo; 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):

View File

@@ -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 &ldquo;reflect&rdquo; 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 &quot;boostification&quot;
has been accepted for inclusion into the boost libraries pending &ldquo;boostification&ldquo;
(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>
&copy; 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 &ldquo;as is&rdquo; 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

View File

@@ -11,11 +11,14 @@
A Peek Under the Hood
</h1>
<p>
<code> extension_class&lt;T&gt;</code> is a subclass of <code>
Declaring a <code>class_builder&lt;T&gt;</code> causes the instantiation
of an <code>extension_class&lt;T&gt;</code> to which it forwards all
member function calls and which is doing most of the real work.
<code>extension_class&lt;T&gt;</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&lt;&gt;</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&lt;&gt;</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>
&copy; Copyright David Abrahams 2000. Permission to copy, use, modify,