mirror of
https://github.com/boostorg/python.git
synced 2026-01-22 05:22:45 +00:00
Release 2000-11-06
[SVN r8151]
This commit is contained in:
68
enums.html
Normal file
68
enums.html
Normal file
@@ -0,0 +1,68 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Wrapping enums
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="c++boost.gif" alt= "c++boost.gif (8819 bytes)">Wrapping enums
|
||||
</h1>
|
||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
||||
is an enumeration constant, py_cpp cannot automatically convert enum values to
|
||||
and from Python. To handle this case, you need to decide how you want the enum
|
||||
to show up in Python (since Python doesn't have enums). If you are satisfied
|
||||
with a Python int as a way to represent your enum values, you can write some
|
||||
simple <code>from_python()</code> and <code>to_python()</code> functions in
|
||||
<code>namespace py::</code>
|
||||
|
||||
<blockquote><pre>
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE // workaround GCC 2.95.2 bug
|
||||
namespace py {
|
||||
#endif
|
||||
|
||||
MyEnumType from_python(PyObject* x,
|
||||
py::Type<MyEnumType>)
|
||||
{
|
||||
return static_cast<MyEnum>(
|
||||
from_python(x, py::Type<long>()));
|
||||
}
|
||||
|
||||
PyObject* to_python(MyEnumType x)
|
||||
{
|
||||
return to_python(static_cast<long>(x));
|
||||
}
|
||||
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
</pre></blockquote>
|
||||
This technique defines the conversions of
|
||||
<code>MyEnumType</code> in terms of the conversions for the built-in
|
||||
<code>long</code> type.
|
||||
|
||||
You may also want to add a bunch of lines like this to your module
|
||||
initialization:
|
||||
|
||||
<blockquote><pre>
|
||||
mymodule.add(py::to_python(enum_value_1), "enum_value_1");
|
||||
mymodule.add(py::to_python(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
You can also add these to an extension class definition:
|
||||
<blockquote><pre>
|
||||
my_class.add(py::to_python(enum_value_1), "enum_value_1");
|
||||
my_class.add(py::to_python(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
<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.
|
||||
<p>
|
||||
Updated: Nov 5, 2000
|
||||
</div>
|
||||
|
||||
@@ -35,31 +35,32 @@
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Reflecting C++ Inheritance Relationships</h2>
|
||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||||
<p>
|
||||
Py_cpp also allows us to represent C++ inheritance relationships so that
|
||||
wrapped derived classes may be passed where values, pointers, or
|
||||
references to a base class are expected as arguments:
|
||||
references to a base class are expected as arguments. The
|
||||
<code>declare_base</code> member function of
|
||||
<code>ClassWrapper<></code> is used to establish the relationship
|
||||
between base and derived classes:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <memory> // for std::auto_ptr<>
|
||||
#include <memory> // for std::auto_ptr<>
|
||||
|
||||
struct Base
|
||||
{
|
||||
struct Base {
|
||||
virtual ~Base() {}
|
||||
virtual const char* name() const { return "Base"; }
|
||||
};
|
||||
|
||||
struct Derived
|
||||
{
|
||||
struct Derived : Base {
|
||||
Derived() : x(-1) {}
|
||||
virtual const char* name() const { return "Derived"; }
|
||||
int x;
|
||||
};
|
||||
|
||||
std::auto_ptr<Base> base_factory() {
|
||||
return std::auto_ptr<Base>(new Derived);
|
||||
std::auto_ptr<Base> derived_as_base() {
|
||||
return std::auto_ptr<Base>(new Derived);
|
||||
}
|
||||
|
||||
const char* get_name(const Base& b) {
|
||||
@@ -86,10 +87,10 @@ void initmy_module()
|
||||
|
||||
py::ClassWrapper<Derived> derived_class(my_module, "Derived");
|
||||
derived_class.def(py::Constructor<void>());
|
||||
// This establishes the inheritance relationship between Base and Derived
|
||||
derived_class.declare_base(base_class);
|
||||
<b>// Establish the inheritance relationship between Base and Derived
|
||||
derived_class.declare_base(base_class);</b>
|
||||
|
||||
my_module.def(base_factory, "base_factory");
|
||||
my_module.def(derived_as_base, "derived_as_base");
|
||||
my_module.def(get_name, "get_name");
|
||||
my_module.def(get_derived_x, "get_derived_x");
|
||||
}
|
||||
@@ -110,12 +111,12 @@ void initmy_module()
|
||||
>>> derived = Derived()
|
||||
>>> get_name(base)
|
||||
'Base'
|
||||
>>> # objects of wrapped class Derived may be passed where Base is expected
|
||||
</pre><i>objects of wrapped class Derived may be passed where Base is expected</i><pre>
|
||||
>>> get_name(derived)
|
||||
'Derived'
|
||||
>>> # objects of wrapped class Derived can be passed where Derived is
|
||||
>>> # expected but where type information has been lost.
|
||||
>>> get_derived_x(base_factory())
|
||||
</pre><i>objects of wrapped class Derived can be passed where Derived is
|
||||
expected but where type information has been lost.</i><pre>
|
||||
>>> get_derived_x(derived_as_base())
|
||||
-1
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
206
overriding.html
206
overriding.html
@@ -1,96 +1,105 @@
|
||||
<!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
|
||||
|
||||
<title>Overridable Virtual Functions</title>
|
||||
|
||||
<img src="c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
||||
width="277" height="86">
|
||||
|
||||
<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>.
|
||||
|
||||
|
||||
<h2><a name="overriding_example">Example</a></h2>
|
||||
|
||||
<p>In this example, it is assumed that <code>world::get()</code> is a virtual
|
||||
member function:
|
||||
|
||||
<blockquote><pre>
|
||||
class 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<const char*>::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(hello::world* self) const
|
||||
{ return self->hello::world::get(); }
|
||||
private:
|
||||
PyObject* m_self; // A way to hold onto the Python object
|
||||
public:
|
||||
world(int);
|
||||
virtual ~world();
|
||||
<b>virtual</b> const char* get() const { return "hi, world"; }
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Finally, we add <code>world_callback</code> to the <code>
|
||||
ClassWrapper<></code> declaration in our module initialization
|
||||
function:
|
||||
<blockquote>
|
||||
<pre>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
We'll need a derived class<a href="#why_derived">*</a> to help us
|
||||
dispatch the call to Python. In our derived class, we need the following
|
||||
elements:
|
||||
|
||||
<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_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>py::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.
|
||||
|
||||
</ol>
|
||||
|
||||
<blockquote><pre>
|
||||
struct world_callback : world
|
||||
{
|
||||
world_callback(PyObject* self, int x) // <a href="#derived_2">2</a>
|
||||
: world(x),
|
||||
m_self(self) {}
|
||||
|
||||
const char* get() const // <a href="#derived_3">3</a>
|
||||
{ return py::Callback<const char*>::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>
|
||||
{ return self.world::get(); }
|
||||
private:
|
||||
PyObject* m_self; // <a href="#derived_1">1</a>
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Finally, we add <code>world_callback</code> to the <code>
|
||||
ClassWrapper<></code> declaration in our module initialization
|
||||
function, and when we define the function, we must tell py_cpp about the default
|
||||
implementation:
|
||||
|
||||
<blockquote><pre>
|
||||
// Create the <a name=
|
||||
"world_class">Python type object</a> for our extension class
|
||||
py::ClassWrapper<hello::world<strong>,world_callback></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(&hello::world::get, "get", &world_callback::default_get);
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Now our subclass of <code>hello.world</code> behaves as expected:
|
||||
<p>
|
||||
<blockquote>
|
||||
<pre>
|
||||
world_class.def(&world::get, "get", &<b>world_callback::default_get</b>);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Now our subclass of <code>hello.world</code> behaves as expected:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> hello.length(my_subclass())
|
||||
12
|
||||
</pre>
|
||||
</blockquote>
|
||||
</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
|
||||
@@ -99,9 +108,9 @@ world_class.def(&hello::world::get, "get", &world_callback::default_get)
|
||||
possible to expose the interface for a 3rd party library without changing
|
||||
it. To unintrusively hook into the virtual functions so that a Python
|
||||
override may be called, we must use a derived class.
|
||||
<h2>
|
||||
Pure Virtual Functions
|
||||
</h2>
|
||||
|
||||
<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
|
||||
@@ -114,14 +123,12 @@ world_class.def(&hello::world::get, "get", &world_callback::default_get)
|
||||
function, indicating that it should have been implemented. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
struct baz
|
||||
{
|
||||
<strong>virtual</strong> void pure(int) = 0;
|
||||
struct baz {
|
||||
<strong>virtual</strong> int pure(int) = 0;
|
||||
};
|
||||
|
||||
struct baz_callback
|
||||
{
|
||||
void pure(int x) { py::Callback<void>::call_method(m_self, "pure", x); }
|
||||
struct baz_callback {
|
||||
int pure(int x) { py::Callback<int>::call_method(m_self, "pure", x); }
|
||||
};
|
||||
|
||||
extern "C"
|
||||
@@ -149,18 +156,29 @@ initfoobar()
|
||||
<pre>
|
||||
>>> from foobar import baz
|
||||
>>> x = baz()
|
||||
>>> x.pure()
|
||||
>>> x.pure(1)
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: pure
|
||||
>>> class mumble(baz):
|
||||
... def pure(self, z): pass
|
||||
... def pure(self, x): return x + 1
|
||||
...
|
||||
>>> y = mumble()
|
||||
>>> y.pure()
|
||||
>>>
|
||||
</pre>
|
||||
</blockquote>
|
||||
>>> y.pure(99)
|
||||
100
|
||||
</pre></blockquote>
|
||||
|
||||
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
|
||||
|
||||
<p>This is one area where some minor intrusiveness on the wrapped library is
|
||||
required. Once it has been overridden, the only way to call the base class
|
||||
implementation of a private virtual function is to make the derived class a
|
||||
friend of the base class. You didn't hear it from me, but most C++
|
||||
implementations will allow you to change the declaration of the base class in
|
||||
this limited way without breaking binary compatibility (though it will certainly
|
||||
break the <a
|
||||
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
|
||||
|
||||
<p>
|
||||
Prev: <a href="example1.html">A Simple Example Using py_cpp</a> Next: <a
|
||||
href="overloading.html">Function Overloading</a> Up: <a href=
|
||||
|
||||
151
pointers.html
Normal file
151
pointers.html
Normal file
@@ -0,0 +1,151 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Pointers
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<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>
|
||||
<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?
|
||||
A pointer to a single element? An array? When used as a return value, is the
|
||||
caller expected to manage (delete) the pointed-to object or is the pointer
|
||||
really just a reference? If the latter, what happens to Python references to the
|
||||
referent when some C++ code deletes it?
|
||||
<p>
|
||||
There are a few cases in which pointers are converted automatically:
|
||||
<ul>
|
||||
|
||||
<li>Both const- and non-const pointers to wrapped class instances can be passed
|
||||
<i>to</i> C++ functions.
|
||||
|
||||
<li>Values of type <code>const char*</code> are interpreted as
|
||||
null-terminated 'C' strings and when passed to or returned from C++ functions are
|
||||
converted from/to Python strings.
|
||||
|
||||
</ul>
|
||||
|
||||
<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
|
||||
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
|
||||
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):
|
||||
|
||||
<blockquote><pre>
|
||||
const Foo* f(); // original function
|
||||
const Foo& f_wrapper() { return *f(); }
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
|
||||
<h2>Dealing with the problem</h2>
|
||||
|
||||
<p>The first step in handling the remaining cases is to figure out what the pointer
|
||||
means. Several potential solutions are provided in the examples that follow:
|
||||
|
||||
<h3>Returning a pointer to a wrapped type</h3>
|
||||
|
||||
<h4>Returning a const pointer</h4>
|
||||
|
||||
<p>If you have lots of functions returning a <code>const T*</code> for some
|
||||
wrapped <code>T</code>, you may want to provide an automatic
|
||||
<code>to_python</code> conversion function so you don't have to write lots of
|
||||
thin wrappers. You can do this simply as follows:
|
||||
|
||||
<blockquote><pre>
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE // work around gcc 2.95.2 bug
|
||||
namespace py {
|
||||
#endif
|
||||
PyObject* to_python(const Foo* p) {
|
||||
return to_python(*p); // convert const Foo* in terms of const Foo&
|
||||
}
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
</pre></blockquote>
|
||||
|
||||
<h4>If you can't (afford to) copy the referent, or the pointer is non-const</h4>
|
||||
|
||||
<p>If the wrapped type doesn't have a public copy constructor, if copying is
|
||||
<i>extremely</i> costly (remember, we're dealing with Python here), or if the
|
||||
pointer is non-const and you really need to be able to modify the referent from
|
||||
Python, you can use the following dangerous trick. Why dangerous? Because python
|
||||
can not control the lifetime of the referent, so it may be destroyed by your C++
|
||||
code before the last Python reference to it disappears:
|
||||
|
||||
<blockquote><pre>
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE // work around gcc 2.95.2 bug
|
||||
namespace py {
|
||||
#endif
|
||||
PyObject* to_python(Foo* p)
|
||||
{
|
||||
return py::PyExtensionClassConverters<Foo>::ptr_to_python(p);
|
||||
}
|
||||
|
||||
PyObject* to_python(const Foo* p)
|
||||
{
|
||||
return to_python(const_cast<Foo*>(p));
|
||||
}
|
||||
#ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
</pre></blockquote>
|
||||
|
||||
This will cause the Foo* to be treated as though it were an owning smart
|
||||
pointer, even though it's not. Be sure you don't use the reference for anything
|
||||
from Python once the pointer becomes invalid, though. Don't worry too much about
|
||||
the <code>const_cast<></code> above: Const-correctness is completely lost
|
||||
to Python anyway!
|
||||
|
||||
<h3>[In/]Out Parameters and Immutable Types</h3>
|
||||
|
||||
<p>If you have an interface that uses non-const pointers (or references) as
|
||||
in/out parameters to types which in Python are immutable (e.g. int, string),
|
||||
there simply is <i>no way</i> to get the same interface in Python. You must
|
||||
resort to transforming your interface with simple thin wrappers as shown below:
|
||||
<blockquote><pre>
|
||||
const void f(int* in_out_x); // original function
|
||||
const int f_wrapper(int in_x) { f(in_x); return in_x; }
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Of course, [in/]out parameters commonly occur only when there is already a
|
||||
return value. You can handle this case by returning a Python tuple:
|
||||
<blockquote><pre>
|
||||
typedef unsigned ErrorCode;
|
||||
const char* f(int* in_out_x); // original function
|
||||
...
|
||||
#include <py_cpp/objects.h>
|
||||
const py::Tuple f_wrapper(int in_x) {
|
||||
const char* s = f(in_x);
|
||||
return py::Tuple(s, in_x);
|
||||
}
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
<p>Now, in Python:
|
||||
<blockquote><pre>
|
||||
>>> str,out_x = f(3)
|
||||
</pre></blockquote>
|
||||
|
||||
|
||||
|
||||
<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.
|
||||
<p>
|
||||
Updated: Nov 6, 2000
|
||||
</div>
|
||||
|
||||
175
py_cpp.html
175
py_cpp.html
@@ -8,77 +8,144 @@
|
||||
<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
|
||||
The source code for py_cpp, including a MSVC demo project is available <a
|
||||
href="py_cpp_20001106.zip">here</a>.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
<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.
|
||||
|
||||
<h2>Supported Platforms</h2>
|
||||
<p>py_cpp has been tested in the following configurations:
|
||||
|
||||
<ul>
|
||||
<li>Against Python 1.5.2 using the following compiler/library:
|
||||
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
||||
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>/<a
|
||||
href="http://www.stlport.org">STLport 4.0</a>
|
||||
|
||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a> [by <a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich
|
||||
Koethe</a>]
|
||||
|
||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a>/<a href="http://www.stlport.org">STLport 4.0</a>
|
||||
|
||||
<li>Compaq C++ V6.2-024 for Digital UNIX V5.0 Rev. 910 (an <a
|
||||
href="http://www.edg.com/">EDG</a>-based compiler) with <a
|
||||
href="http://www.stlport.org/beta.html">STLport-4.1b3</a> [by <a
|
||||
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
||||
|
||||
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
||||
Pro6 for Windows</a> (the first release has a bug that's fatal to py_cpp)
|
||||
</ul>
|
||||
<br>
|
||||
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a> [by
|
||||
<a href="mailto:aleaxit@yahoo.com">Alex Martelli</a>]
|
||||
</ul>
|
||||
</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"
|
||||
(completion of the documentation, change in some naming conventions and
|
||||
resolution of some namespace issues).
|
||||
|
||||
<h2>Credits</h2>
|
||||
<p>
|
||||
The source code for py_cpp, including a MSVC demo project is available <a
|
||||
href="py_cpp_20001102.zip">here</a>. It has been tested against Python
|
||||
1.5.2 with GCC 2.95.2 and 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 MSVC++ 6sp4 by Alex
|
||||
Martelli. It will work with the next release of Metrowerks CodeWarrior
|
||||
Pro6 (the first release has a bug that's fatal to py_cpp_). 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>
|
||||
<ul>
|
||||
<li><a href="mailto:abrahams@mediaone.net">David Abrahams</a> originated
|
||||
and wrote py_cpp.
|
||||
|
||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
||||
had independently developed a similar system. When he discovered py_cpp,
|
||||
he generously contributed countless hours of coding and much insight into
|
||||
improving it. He is responsible for an early version of the support for <a
|
||||
href="overloading.html">function overloading</a> and wrote the support for
|
||||
<a href="inheritance.html#implicit_conversion">reflecting C++ inheritance
|
||||
relationships</a>. He has helped to improve error-reporting from both
|
||||
Python and C++, and is currently doing valuable research into <a
|
||||
href="special.html#reasons">the best approach for numeric coercion</a>.
|
||||
|
||||
<li>The members of the boost mailing list and the Python community supplied
|
||||
invaluable early feedback. In particular, Ron Clarke, Mark Evans, Anton
|
||||
Gluck, Ralf W. Grosse-Kunstleve, Prabhu Ramachandran, and Barry Scott took
|
||||
the brave step of trying to use py_cpp while it was still in early stages
|
||||
of development.
|
||||
|
||||
<li>The development of py_cpp wouldn't have been
|
||||
possible without the generous support of <a href="http://www.dragonsys.com/">Dragon Systems/Lernout and
|
||||
Hauspie, Inc</a> who supported its development as an open-source project.
|
||||
</ul>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<a href="extending.html">A Brief Introduction to writing Python
|
||||
<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="inheritance.html">Inheritance</a>
|
||||
<li>
|
||||
<a href="special.html">Special Method Name Support</a>
|
||||
<li>
|
||||
<a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
<li>
|
||||
<a href="building.html">Building a Module with Py_cpp</a>
|
||||
</ol>
|
||||
|
||||
<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="inheritance.html">Inheritance</a>
|
||||
|
||||
<li><a href="special.html">Special Method Name Support</a>
|
||||
|
||||
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
|
||||
<li><a href="building.html">Building a Module with Py_cpp</a>
|
||||
|
||||
<li>Advanced Topics
|
||||
|
||||
<ol>
|
||||
<li>ClassWrapper<>
|
||||
|
||||
<li><a href="enums.html">enums</a>
|
||||
|
||||
<li>References
|
||||
|
||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
|
||||
<li>Built-in Python Types
|
||||
|
||||
<li>Other Extension Types
|
||||
|
||||
<li>Templates
|
||||
</ol>
|
||||
|
||||
</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
|
||||
More sophisticated examples 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>
|
||||
"http://www.egroups.com/list/boost">the boost mailing list</a>.
|
||||
|
||||
<h2>Naming Contest</h2>
|
||||
|
||||
<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
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
======= Release =======
|
||||
2000-11-06 0:22
|
||||
Lots of documentation updates
|
||||
|
||||
added 4-argument template constructor to py::Tuple
|
||||
|
||||
added "add" member function to ClassWrapper<> to allow arbitrary Python
|
||||
objects to be added to an extension class.
|
||||
|
||||
gen_all.py now generates support for n argument member functions and n+1
|
||||
argument member functions at the suggestion of "Ralf W. Grosse-Kunstleve"
|
||||
<rwgk@cci.lbl.gov>
|
||||
|
||||
Added regression tests and re-ordered declare_base calls to verify that the
|
||||
phantom base class issue is resolved.
|
||||
|
||||
2000-11-04 17:35
|
||||
|
||||
Integrated Ullrich Koethe's brilliant from_python_experiment for better
|
||||
@@ -49,6 +65,7 @@
|
||||
|
||||
Remove conflicting /Ot option from vc6_prj release build
|
||||
|
||||
======= Release =======
|
||||
2000-11-02 17:42
|
||||
|
||||
Added a fix for interactions between default virtual function
|
||||
|
||||
Reference in New Issue
Block a user