2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-21 17:12:22 +00:00

Add documentation

[SVN r7959]
This commit is contained in:
Dave Abrahams
2000-10-16 01:37:07 +00:00
parent 38ddc24e58
commit 9227ba0108
7 changed files with 868 additions and 0 deletions

176
comparisons.html Normal file
View File

@@ -0,0 +1,176 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Comparisons with Other Systems
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="c++boost.gif" alt= "c++boost.gif (8819 bytes)">Comparisons with
Other Systems
</h1>
<h2>CXX</h2>
<p>
Like py_cpp, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
provide a C++-oriented interface to Python. In most cases, like py_cpp,
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
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. As far as I can tell, also 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 (less-well) by the py_cpp object wrappers. <a
href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the CXX maintainer,
has told me that what I've described is only half of the picture with
CXX, but I never understood his explanation well-enough to fill in the
other half. I hope that you, dear reader, may be able to help me
complete my comparitive analysis of CXX.
<h2>SWIG</h2>
<p>
<a href= "http://www.swig.org/">SWIG</a> is an impressively mature tool
for exporting an existing ANSI 'C' interface into various scripting
languages. Swig relies on a parser to read your source code and produce
additional source code files which can be compiled into a Python (or
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
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
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
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 doesnt have
this problem[sic]... IMHO overloaded functions are very important to
wrap correctly."<br><i>-Prabhu Ramachandran</i>
</blockquote>
<p>
By contrast, py_cpp doesn't attempt to parse C++ - the problem is simply
too complex to do correctly. Technically, one does write code by hand to
use py_cpp. The goal, however, has been to make that code nearly as
simple as listing the names of the classes and member functions you want
to expose in Python.
<h2>SIP</h2>
<p>
<a
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
is a system similar to SWIG, though seemingly more
C++-oriented. The author says that like py_cpp, SIP supports overriding
extension class member functions in Python subclasses. It appears to
have been designed specifically to directly support some features of
PyQt/PyKDE, which is its primary client. Documentation is almost
entirely missing at the time of this writing, so a detailed comparison
is difficult.
<h2>ILU</h2>
<p>
<a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual">ILU</a>
is a very ambitious project which tries to describe a module's interface
(types and functions) in terms of an <a
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual/manual_2.html">Interface
Specification Language</a> (ISL) so that it can be uniformly interfaced
to a wide range of computer languages, including Common Lisp, C++, C,
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
header file describing the interface, of which the user is expected to
provide an implementation. Unlike py_cpp, this means that the system
imposes implementation details on your C++ code at the deepest level. It
is worth noting that some of the C++ names generated by ILU are supposed
to be reserved to the C++ implementation. It is unclear from the
documentation whether ILU supports overriding C++ virtual functions in Python.
<h2>Zope ExtensionClasses</h2>
<p>
<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
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
Beaudry Hack</a>" that also inspired Don's MESS System.
<p>
The major differences are:
<ul>
<li>
py_cpp lifts the burden on the user to parse and convert function
argument types. Zope provides no such facility.
<li>
py_cpp lifts the burden on the user to maintain Python
reference-counts.
<li>
py_cpp supports function overloading; Zope does not.
<li>
py_cpp supplies a simple mechanism for exposing read-only and
read/write access to data members of the wrapped C++ type as Python
attributes.
<li>
Writing a Zope ExtensionClass is significantly more complex than
exposing a C++ class to python using py_cpp (mostly a summary of the
previous 4 items). <a href=
"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
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
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."
<li>
Zope's Extension SubClasses admit multiple-inheritance from both Zope
ExtensionClasses <i>and</i> Python classes. This capability is currently
not available in py_cpp.
<li>
Zope supplies the standard special Python class attributes __doc__,
__name__, __bases__, __dict__, and __module__ on its
ExtensionClasses; py_cpp does not (coming soon)
<li>
Zope supplies some creative but esoteric idioms such as <a href=
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
Acquisition</a>.
<li>
Zope's ComputedAttribute support is designed to be used from Python.
The analogous feature of py_cp is designed to be used from C++ (I
make no claims that the py_cpp mechanism is more useful than the Zope
mechanism in this case)
</ul>
<p>
Also, the Zope docs say: "The first superclass listed in the class
statement defining an extension subclass must be either a base
extension class or an extension subclass. This restriction will be
removed in Python-1.5." I believe that this promise was made
prematurely. I have looked at the Python 1.5.2 source code and I don't
believe it is possible to deliver on it.
<p>
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
Next: <a href="example1.html">A Simple Example Using py_cpp</a>
Up: <a href="py_cpp.html">Top</a>
<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.
<p>
Updated: Oct 15, 2000
</div>

127
example1.html Normal file
View File

@@ -0,0 +1,127 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
A Simple Example Using py_cpp
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" src="c++boost.gif" alt=
"c++boost.gif (8819 bytes)">
</h1>
<h1>
A Simple Example Using py_cpp
</h1>
<p>
Suppose we have the following C++ API which we want to expose in
Python:
<blockquote>
<pre>
namespace hello {
  class world
  {
   public:
      world(int);
      ~world();
      const char* get() const { return "hi, world"; }
    ...
  };
  void length(const world&amp; x) { return std::strlen(x.get()); }
}
</pre>
</blockquote>
<p>
Here is the C++ code for a python module called <code>hello</code>
which exposes the API using py_cpp:
<blockquote>
<pre>
#include &lt;py_cpp/class_wrapper.h&gt;
// Python requires an exported function called init&lt;module-name&gt; in every
// extension module. This is where we build the module contents.
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
void inithello()
{
    try
    {
       // create an object representing this extension module
       py::Module hello("hello");
       // Create the Python type object for our extension class
       py::ClassWrapper&lt;hello::world&gt; world_class(hello, "world");
       // Add the __init__ function
       world_class.def(py::Constructor&lt;int&gt;());
       // Add a regular member function
       world_class.def(&amp;hello::world::get, "get");
       // Add a regular function to the module
       hello.def(hello::length, "length");
    }
    catch(...)
    {
       py::handle_exception();    // Deal with the exception for Python
    }
}
// Win32 DLL boilerplate
#if defined(_WIN32)
#include &lt;windows.h&gt;
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
{
    return 1;
}
#endif // _WIN32
</pre>
</blockquote>
<p>
That's it! If we build this shared library and put it on our <code>
PYTHONPATH</code> we can now access our C++ class and function from
Python.
<blockquote>
<pre>
&gt;&gt;&gt; import hello
&gt;&gt;&gt; hi_world = hello.world(3)
&gt;&gt;&gt; hi_world.get()
'hi, world'
&gt;&gt;&gt; hello.length(hi_world)
9
</pre>
</blockquote>
<p>
We can even make a subclass of <code>hello.world</code>:
<blockquote>
<pre>
&gt;&gt;&gt; class my_subclass(hello.world):
...     def get(self):
...         return 'hello, world'
...
&gt;&gt;&gt; y = my_subclass(4)
&gt;&gt;&gt; y.get()
'hello, world'
</pre>
</blockquote>
<p>
Pretty cool! You can't do that with an ordinary Python extension type!
<blockquote>
<pre>
&gt;&gt;&gt; hello.length(y)
9
</pre>
</blockquote>
<p>
Of course, you may now have a slightly empty feeling in the pit of
your little pythonic stomach. Perhaps you feel your subclass deserves
to have a <code>length()</code> of <code>12</code>? If so, <a href=
"overriding.html">read on</a>...
<p>
Previous: <a href="comparisons.html">Comparisons with other systems</a> Next: <a href="overriding.html">Overridable virtual functions</a> Up:
<a href="py_cpp.html">Top</a>
<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.
<p>
Updated: Oct 15, 2000
</div>

73
extending.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Brief Introduction to writing Python extension modules
</title>
<h1>
<img src="c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Brief Introduction to writing Python extension modules
</h1>
<p>
Interfacing any language to Python involves building a module which can
be loaded by the Python interpreter, but which isn't written in Python.
This is known as an <em>extension module</em>. Many of the <a href=
"http://www.python.org/doc/current/lib/lib.html">built-in Python
libraries</a> are constructed in 'C' this way; Python even supplies its
<a href="http://www.python.org/doc/current/lib/types.html">fundamental
types</a> using the same mechanism. An extension module can be statically
linked with the Python interpreter, but it more commonly resides in a
shared library or DLL.
<p>
As you can see from <a href=
"http://www.python.org/doc/current/ext/ext.html"> The Python Extending
and Embedding Tutorial</a>, writing an extension module normally means
worrying about
<ul>
<li>
<a href="http://www.python.org/doc/current/ext/refcounts.html">
maintaining reference counts</a>
<li>
<a href="http://www.python.org/doc/current/ext/callingPython.html"> how
to call back into Python</a>
<li>
<a href="http://www.python.org/doc/current/ext/parseTuple.html">
function argument parsing and typechecking</a>
</ul>
This last item typically occupies a great deal of code in an extension
module. Remember that Python is a completely dynamic language. A callable
object receives its arguments in a tuple; it is up to that object to
extract those arguments from the tuple, check their types, and raise
appropriate exceptions. There are numerous other tedious details that need
to be managed; too many to mention here. Py_cpp is designed to lift most of
that burden.<br>
<br>
<p>
Another obstacle that most people run into eventually when extending
Python is that there's no way to make a true Python class in an extension
module. The typical solution is to create a new Python type in the
extension module, and then write an additional module in 100% Python. The
Python module defines a Python class which dispatches to an instance of
the extension type, which it contains. This allows users to write
subclasses of the class in the Python module, almost as though they were
sublcassing the extension type. Aside from being tedious, it's not really
the same as having a true class, because there's no way for the user to
override a method of the extension type which is called from the
extension module. Py_cpp solves this problem by taking advantage of <a
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
feature</a> to provide objects which look, walk, and hiss almost exactly
like regular Python classes. Py_cpp classes are actually cleaner than
Python classes in some subtle ways; a more detailed discussion will
follow (someday).</p>
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
href="py_cpp.html">Top</a> </p>
<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.</p>

139
overloading.html Normal file
View File

@@ -0,0 +1,139 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<title>
Function Overloading
</title>
<div>
<h1>
<img width="277" height="86" id="_x0000_i1025" align="center"
src="c++boost.gif" alt= "c++boost.gif (8819 bytes)">Function Overloading
</h1>
<h2>An Example</h2>
<p>
To expose overloaded functions in Python, simply <code>def()</code> each
one with the same Python name:
<blockquote>
<pre>
inline int f1() { return 3; }
inline int f2(int x) { return x + 1; }
class X {
public:
X() : m_value(0) {}
X(int n) : m_value(n) {}
int value() const { return m_value; }
void value(int v) { m_value = v; }
private:
int m_value;
};
...
void initoverload_demo()
{
    try
    {
py::Module overload_demo("overload_demo");
// Overloaded functions at module scope
overload_demo.def(f1, "f");
overload_demo.def(f2, "f");
py::ClassWrapper&lt;X&gt; x_class(overload_demo, "X");
// Overloaded constructors
x_class.def(py::Constructor&lt;&gt;());
x_class.def(py::Constructor&lt;int&gt;());
// Overloaded member functions
x_class.def((int (X::*)() const)&amp;X::value, "value");
x_class.def((void (X::*)(int))&amp;X::value, "value");
...
</pre>
</blockquote>
<p>
Now in Python:
<blockquote>
<pre>
>>> from overload_demo import *
>>> x0 = X()
>>> x1 = X(1)
>>> x0.value()
0
>>> x1.value()
1
>>> x0.value(3)
>>> x0.value()
3
>>> X('hello')
TypeError: No overloaded functions match (X, string). Candidates are:
void (*)()
void (*)(int)
>>> f()
3
>>> f(4)
5
</pre>
</blockquote>
<h2>Discussion</h2>
<p>
Notice that overloading in the Python module was produced three ways:<ol>
<li>by combining the non-overloaded C++ functions <code>int f1()</code>
and <code>int f2(int)</code> and exposing them as <code>f</code> in Python.
<li>by exposing the overloaded constructors of <code>class X</code>
<li>by exposing the overloaded member functions <code>X::value</code>.
</ol>
<p>
Techniques 1. and 3. above are really alternatives. In case 3, you need
to form a pointer to each of the overloaded functions. The casting
syntax shown above is one way to do that in C++. Case 1 does not require
complicated-looking casts, but may not be viable if you can't change
your C++ interface. N.B. There's really nothing unsafe about casting an
overloaded (member) function address this way: the compiler won't let
you write it at all unless you get it right.
<h2>An Alternative to Casting</h2>
<p>
This approach is not neccessarily better, but may be preferable for some
people who have trouble writing out the types of (member) function
pointers or simply prefer to avoid all casts as a matter of principle:
<blockquote>
<pre>
// Forwarding functions for X::value
inline void set_x_value(X&amp; self, int v) { self.value(v); }
inline int get_x_value(X&amp; self) { return self.value(); }
...
// Overloaded member functions
x_class.def(set_x_value, "value");
x_class.def(get_x_value, "value");
</pre>
</blockquote>
<p>Here we are taking advantage of the ability to expose C++ functions at
namespace scope functions as Python member functions.
<h2>Overload Resolution</h2>
<p>
The function overload resolution mechanism in py_cpp works as
follows:<ul>
<li>Attribute lookup for extension classes proceeds in the usual way. When a
class is found which has a matching attribute, only functions overloaded
in the context of that class are candidates for overload resolution.
<li>Within a name-space context (extension class or module), overloaded
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.
</ul>
<p>
Prev: <a href="overloading.html">Function Overloading</a>
Next: <a href="under-the-hoold.html">A Peek Under the Hood</a>
Up: <a href="py_cpp.html">Top</a>
<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.
<p>
Updated: Oct 15, 2000
</div>

175
overriding.html Normal file
View File

@@ -0,0 +1,175 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
Overridable Virtual Functions
</title>
<h1>
<img src="c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
Overridable Virtual Functions
</h1>
<p>
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>. Of course, the first
step if we want it to act like a virtual function when called from our
C++ code, is to <em>make</em> it virtual:
<blockquote>
<pre>
class world
{
...
<strong>virtual</strong> const char* get() const { return "hi, world"; }
...
};
</pre>
</blockquote>
<p>
Then we'll need a derived class<a href="#why_derived">*</a> to help us
dispatch the call to Python:
<blockquote>
<pre>
struct world_callback : hello::world
{
// The first argument must by a PyObject* (the corresponding Python object)
// The rest of the argument list should match the base class constructor
world_callback(PyObject* self, int x)
: world(x), // dispatch to base object
m_self(self) {} // hang onto the Python object
// Dispatch the call to Python
const char* get() const
{
// Any function arguments would go at the end of the argument list
// The return type is a template parameter
return py::Callback&lt;const char*&gt;::call_method(m_self, "get");
}
// <a name=
"default_implementation">Something Python can call</a> in case there is no override of get()
const char* default_get() const
{ return this-&gt;hello::world::get(); }
private:
PyObject* m_self; // A way to hold onto the Python object
};
</pre>
</blockquote>
<p>
Finally, we add <code>world_callback</code> to the <code>
ClassWrapper&lt;&gt;</code> declaration in our module initialization
function:
<blockquote>
<pre>
// Create the <a name=
"world_class">Python type object</a> for our extension class
py::ClassWrapper&lt;hello::world<strong>,world_callback&gt;</strong> world_class(hello, "world");
...
</pre>
</blockquote>
<p>
...and when we define the function, we must tell py_cpp about the default
implementation:
<blockquote>
<pre>
// Add a virtual member function
world_class.def(&amp;hello::world::get, "get", &amp;world_callback::default_get);
</pre>
</blockquote>
<p>
Now our subclass of <code>hello.world</code> behaves as expected:
<p>
<blockquote>
<pre>
&gt;&gt;&gt; class my_subclass(hello.world):
... def get(self):
... return 'hello, world'
...
&gt;&gt;&gt; hello.length(my_subclass())
12
</pre>
</blockquote>
<p>
<a name="why_derived">*</a>You may ask, "Why do we need this derived
class? This could have been designed so that everything gets done right
inside of <code>hello::world</code>." One of the goals of py_cpp 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.
<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
<code>def()</code> on the <code>ExtensionClass&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:
<blockquote>
<pre>
struct baz
{
<strong>virtual</strong> void pure(int) = 0;
};
struct baz_callback
{
void pure(int x) { py::Callback&lt;void&gt;::call_method(m_self, "pure", x); }
};
extern "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
initfoobar()
{
try
{
py::Module foobar("foobar");
py::ClassWrapper&lt;baz,baz_callback&gt; baz_class("baz");
baz_class.def(&amp;baz::pure, "pure");
}
catch(...)
{
py::handle_exception(); // Deal with the exception for Python
}
}
</pre>
</blockquote>
<p>
Now in Python:
<blockquote>
<pre>
&gt;&gt;&gt; from foobar import baz
&gt;&gt;&gt; x = baz()
&gt;&gt;&gt; x.pure()
Traceback (innermost last):
File "&lt;stdin&gt;", line 1, in ?
AttributeError: pure
&gt;&gt;&gt; class mumble(baz):
... def pure(self, z): pass
...
&gt;&gt;&gt; y = mumble()
&gt;&gt;&gt; y.pure()
&gt;&gt;&gt;
</pre>
</blockquote>
<p>
Prev: <a href="example1.html">A Simple Example Using py_cpp</a> Next: <a
href="under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
"py_cpp.html">Top</a>
<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.
<p>
Updated: Sept 30, 2000

120
py_cpp.html Normal file
View File

@@ -0,0 +1,120 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
py_cpp Python/C++ binding documentation
</title>
<h1>
<img src="c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
align="center" height="86"> py_cpp<a href="#naming_contest">*</a>
</h1>
<p>
Py_cpp is a system for quickly and easily interfacing C++ code with <a
href="http:www.python.org">Python</a> such that the Python interface is
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.
<p>
The source code for py_cpp, including a MSVC demo project is available
<a href="py_cpp_20001013.zip">here</a>. It has been tested against Python
1.5.2 with GCC 2.95.2, Metrowerks CodeWarrior Pro6 and with Microsoft
Visual C++ 6 sp4 using both the <a href="http://www.stlport.org">
STLport</a> standard library implementation <em>and</em> the library
implementation which ships with the compiler. It has also been tested
against Python 2.0c1 with an unknown version of MSVC++ by Alex Martelli.
Py_cpp requires the <a href="http://www.boost.org">Boost</a> libraries,
and is currently under formal review on <a href=
"http://www.egroups.com/list/boost">the boost mailing list</a> for
acceptance into boost.
<p>
py_cpp was originally written by David Abrahams. Ullrich Koethe supplied
an early version of the overloading support and wrote the support for
implicit conversions of arguments that have a C++ inheritance
relationship. Alex Martelli supplied the first tests against Python 2.0.
The members of the boost mailing list and the Python community supplied
invaluable early feedback. The development of py_cpp wouldn't have been
possible without the generous support of Dragon Systems/Lernout and
Hauspie, Inc.
<h2>
Table of Contents
</h2>
<ol>
<li>
<a href="extending.html">A Brief Introduction to writing Python
extension modules</a>
<li>
<a href="comparisons.html">Comparisons between py_cpp and other systems
for extending Python</a>
<li>
<a href="example1.html">A Simple Example Using py_cpp</a>
<li>
<a href="overriding.html">Overridable Virtual Functions</a>
<li>
<a href="overloading.html">Function Overloading</a>
<li>
<a href="under-the-hood.html">A Peek Under the Hood</a>
</ol>
<p>
More sophisticated examples, including examples which demonstrate that
these ExtensionClasses support some of Python's "special" member
functions (e.g. <code>__getattr__(self, name)</code>), are given in
<code>extclass_demo.cpp</code>, <code> extclass_demo.h</code>, and <code>
test_extclass.py</code> in the <a href="py_cpp.tgz">source code
archive</a>. There's much more here, and much more documentation to
come...
<p>
Questions should be directed to <a href=
"http://www.egroups.com/list/boost">the boost mailing list</a> or to <a
href="mailto:abrahams@mediaone.net"> David Abrahams</a>, the primary
author and maintainer.
<h3>
Naming Contest
</h3>
<p>
Yes, I know py_cpp is a lousy name. Problem is, the best names my puny
imagination can muster (IDLE and GRAIL) are taken, so I'm holding a
naming contest. First prize? You get to pick the name&lt;0.2wink&gt; and
you will be credited in the documentation. Names that have been suggested
so far include:
<ul>
<li>
Py++
<li>
Python++
<li>
Coil
<li>
SnakeSkin
<li>
CCCP - <strong>C</strong>onvert <strong>C</strong>++ <strong>
C</strong>lasses to <strong>P</strong>ython
<li>
C<sup>3</sup>PO - <strong>C</strong>onvert <strong>C</strong>++
<strong>C</strong>lasses to <strong>P</strong>ython <strong>
O</strong>bjects
<li>
PALIN - <strong>P</strong>ython <strong>
A</strong>ugmented-<strong>L</strong>anguage <strong>
IN</strong>tegration
<li>
C-thru
<li>
SeamlessC
<li>
BorderCrossing
</ul>
Please <a href="http://www.egroups.com/list/boost">post</a> or send <a
href="http:mailto:abrahams@mediaone.net">me</a> your suggestions!<br>
<br>
<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.
<p>
Updated: Oct 15, 2000

58
under-the-hood.html Normal file
View File

@@ -0,0 +1,58 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>
A Peek Under the Hood
</title>
<h1>
<img src="c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
width="277" height="86">
</h1>
<h1>
A Peek Under the Hood
</h1>
<p>
<code> ExtensionClass&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 instance of
the <code>ExtensionClass&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>
Py_cpp uses C++'s template argument deduction mechanism to determine the
types of arguments to functions (except constructors, for which we must
<a href="example1.html#Constructor_example">provide an argument list</a>
because they can't be named in C++). Then, it calls the appropriate
overloaded functions <code>PyObject*
to_python(</code><em>S</em><code>)</code> and <em>
S'</em><code>from_python(PyObject*,
Type&lt;</code><em>S</em><code>&gt;)</code> which convert between any C++
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
reference to any Python object in its 'C' API. The <a href=
"example1.html#world_class"><code>ExtensionClass&lt;T&gt;</code></a>
template defines a whole raft of these conversions (for <code>T, T*,
T&amp;, std::auto_ptr&lt;T&gt;</code>, etc.), using the same inline
friend function technique employed by <a href=
"http://www.boost.org/libs/utility/operators.htm">the boost operators
library</a>.
<p>
Because the <code>to_python</code> and <code>from_python</code> functions
for a user-defined class are defined by <code>
ExtensionClass&lt;T&gt;</code>, it is important that an instantiation of
<code> ExtensionClass&lt;T&gt;</code> is visible to any code which wraps
a C++ function with a <code>T, T*, const T&amp;</code>, etc. parameter or
return value. In particular, you may want to create all of the classes at
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> Up: <a
href="py_cpp.html">Top</a>
<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.
<p>
Updated: Sept 30, 2000