2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-28 19:32:14 +00:00

This commit was manufactured by cvs2svn to create branch

'unlabeled-1.1.2'.

[SVN r9018]
This commit is contained in:
nobody
2001-02-07 23:58:45 +00:00
12 changed files with 521 additions and 0 deletions

6
example/README Normal file
View File

@@ -0,0 +1,6 @@
To get started with the Boost Python Library, use the examples
getting_started?.cpp and abstract.cpp.
The files example1.cpp and rwgk1.cpp are obsolete. They are only
included because the makefiles in the build directory still refer to
them. This will be fixed later.

34
example/abstract.cpp Normal file
View File

@@ -0,0 +1,34 @@
// Example by Ullrich Koethe
#include "boost/python/class_builder.hpp"
#include <string>
struct Abstract
{
virtual std::string test() = 0;
};
struct Abstract_callback: Abstract
{
Abstract_callback(PyObject * self)
: m_self(self)
{}
std::string test()
{
return boost::python::callback<std::string>::call_method(m_self, "test");
}
PyObject * m_self;
};
extern "C"
DL_EXPORT(void)
initabstract()
{
boost::python::module_builder a("abstract");
boost::python::class_builder<Abstract, Abstract_callback>
a_class(a, "Abstract");
a_class.def(boost::python::constructor<>()); // wrap a constructor
a_class.def(&Abstract::test, "test");
}

View File

@@ -0,0 +1,32 @@
#include <string>
namespace { // Avoid cluttering the global namespace.
// A couple of simple C++ functions that we want to expose to Python.
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
}
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
extern "C"
DL_EXPORT(void)
initgetting_started1()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("getting_started1");
// Add regular functions to the module.
this_module.def(greet, "greet");
this_module.def(square, "square");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,51 @@
#include <iostream>
#include <string>
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class world
{
private:
std::string country;
public:
world(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country + "!"; }
};
// A function taking a world object as an argument.
std::string invite(const world& w) {
return w.greet() + " Please come soon!";
}
}
extern "C"
DL_EXPORT(void)
initgetting_started2()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("getting_started2");
// Create the Python type object for our extension class.
python::class_builder<world> world_class(this_module, "world");
// Add the __init__ function.
world_class.def(python::constructor<std::string>());
// Add a regular member function.
world_class.def(&world::greet, "greet");
// Add invite() as a regular function to the module.
this_module.def(invite, "invite");
// Even better, invite() can also be made a member of world_class!!!
world_class.def(invite, "invite");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,122 @@
/*
This example shows how to make an Extension Class "pickleable".
Python's pickle module implements a basic but powerful algorithm
for "pickling" (a.k.a. serializing, marshalling or flattening)
nearly arbitrary Python objects.
The user can influence how an Extension Class instance is pickled
by defining three special methods: __getinitargs__(),
__getstate__(), and __setstate(). This interface is similar to
that for regular Python classes as described in detail in the
Python Library Reference for pickle:
http://www.python.org/doc/current/lib/module-pickle.html
When an Extension Class instance is pickled, __getinitargs__() is
called, if implemented. This method should return a tuple
containing the arguments to be passed to the class constructor when
the object is restored.
If there is no __getstate__() method, the instance's __dict__ is
pickled if it is not empty. If __getstate__() is defined, it should
return an object representing the state of the instance.
If there is no __setstate__() method, __getstate__() must return a
dictionary. When the instance is restored, the items in this dictionary
are added to the instance's __dict__.
If the Extension Class defines __setstate__(), the pickle loader
calls it with the result of __getstate__() as arguments. In this
case, the state object need not be a dictionary. The
__getstate__() and __setstate__() methods can do what they want.
If both __getinitargs__() and __getstate__() are defined, the
instance is restored by first calling the constructor with
the result of __getinitargs__() as argument. After the instance
is reconstructed, the __dict__ is updated or __setstate__() is
called if implemented.
The mechanism described here is an exact replication of that one
implemented by Jim Fulton's ExtensionClass (included in Zope 2.2.2).
*/
#include <iostream>
#include <string>
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class world
{
private:
std::string country;
int secret_number;
public:
world(const std::string& country) : secret_number(0) {
this->country = country;
}
std::string greet() const { return "Hello from " + country + "!"; }
std::string get_country() const { return country; }
void set_secret_number(int number) { secret_number = number; }
int get_secret_number() const { return secret_number; }
};
// Support for pickle.
python::tuple world_getinitargs(const world& w) {
python::tuple result(1);
result.set_item(0, w.get_country());
return result;
}
python::tuple world_getstate(const world& w) {
python::tuple result(1);
result.set_item(0, w.get_secret_number());
return result;
}
void world_setstate(world& w, python::tuple state) {
if (state.size() != 1) {
PyErr_SetString(PyExc_ValueError,
"Unexpected argument in call to __setstate__.");
throw python::error_already_set();
}
int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(),
python::type<int>());
if (number != 42)
w.set_secret_number(number);
}
}
extern "C"
DL_EXPORT(void)
initgetting_started3()
{
try
{
// Create an object representing this extension module.
python::module_builder this_module("getting_started3");
// Create the Python type object for our extension class.
python::class_builder<world> world_class(this_module, "world");
// Add the __init__ function.
world_class.def(python::constructor<std::string>());
// Add a regular member function.
world_class.def(&world::greet, "greet");
world_class.def(&world::get_secret_number, "get_secret_number");
world_class.def(&world::set_secret_number, "set_secret_number");
// Support for pickle.
world_class.def(world_getinitargs, "__getinitargs__");
world_class.def(world_getstate, "__getstate__");
world_class.def(world_setstate, "__setstate__");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

View File

@@ -0,0 +1,104 @@
#include <boost/python/class_builder.hpp>
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
// A wrapper is used to define additional constructors.
//
struct vector_double_wrapper: std::vector<double>
{
// Tell the compiler how to convert a base class object to
// this wrapper object.
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
: std::vector<double>(vd) {}
vector_double_wrapper(PyObject* self)
: std::vector<double>() {}
vector_double_wrapper(PyObject* self, const int n)
: std::vector<double>(n) {}
vector_double_wrapper(PyObject* self, python::tuple tuple)
: std::vector<double>(tuple.size())
{
std::vector<double>::iterator vd = begin();
for (int i = 0; i < tuple.size(); i++)
vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
python::type<double>());
}
};
double getitem(const std::vector<double>& vd, const std::size_t key) {
return vd[key];
}
void setitem(std::vector<double>& vd, const std::size_t key,
const double &d) {
std::vector<double>::iterator vditer = vd.begin();
vditer[key] = d;
}
void delitem(std::vector<double>& vd, const std::size_t key) {
std::vector<double>::iterator vditer = vd.begin();
vd.erase(&vditer[key]);
}
// Convert vector_double to a regular Python tuple.
//
python::tuple as_tuple(const std::vector<double>& vd)
{
python::tuple t(vd.size());
for (int i = 0; i < vd.size(); i++) t.set_item(i,
python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i])));
return t;
}
// Function returning a vector_double object to Python.
//
std::vector<double> foo(const int n)
{
std::vector<double> vd(n);
std::vector<double>::iterator vditer = vd.begin();
for (int i = 0; i < n; i++) vditer[i] = double(i);
return vd;
}
// Same as foo(), but avoid copying on return.
//
std::auto_ptr<std::vector<double> > bar(const int n)
{
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
std::vector<double>::iterator vditer = vdptr->begin();
for (int i = 0; i < n; i++) vditer[i] = double(10 * i);
return vdptr;
}
}
extern "C"
DL_EXPORT(void)
initgetting_started4()
{
try
{
python::module_builder this_module("getting_started4");
python::class_builder<std::vector<double>, vector_double_wrapper>
vector_double(this_module, "vector_double");
vector_double.def(python::constructor<>());
vector_double.def(python::constructor<const int>());
vector_double.def(python::constructor<python::tuple>());
vector_double.def(&std::vector<double>::size, "__len__");
vector_double.def(getitem, "__getitem__");
vector_double.def(setitem, "__setitem__");
vector_double.def(delitem, "__delitem__");
vector_double.def(as_tuple, "as_tuple");
this_module.def(foo, "foo");
this_module.def(bar, "bar");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}

23
example/test_abstract.py Normal file
View File

@@ -0,0 +1,23 @@
# Example by Ullrich Koethe
r'''>>> from abstract import *
>>> class A(Abstract):
... def __init__(self, text):
... Abstract.__init__(self) # call the base class constructor
... self.text = text
... def test(self): # implement abstract function
... return self.text
...
>>> a = A("Hello")
>>> a.test()
'Hello'
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_abstract
doctest.testmod(test_abstract)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,17 @@
r'''>>> import getting_started1
>>> print getting_started1.greet()
hello, world
>>> number = 11
>>> print number, '*', number, '=', getting_started1.square(number)
11 * 11 = 121
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started1
doctest.testmod(test_getting_started1)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,19 @@
r'''>>> import getting_started2
>>> w = getting_started2.world('California')
>>> print w.greet()
Hello from California!
>>> print getting_started2.invite(w)
Hello from California! Please come soon!
>>> print w.invite()
Hello from California! Please come soon!
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started2
doctest.testmod(test_getting_started2)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,56 @@
r'''>>> import getting_started3
>>> import re
>>> import pickle
>>> getting_started3.world.__module__
'getting_started3'
>>> getting_started3.world.__safe_for_unpickling__
1
>>> getting_started3.world.__reduce__()
'world'
>>> assert re.match(
... "\(<extension class getting_started3.world at [0-9a-fA-FxX]+>, \('Hello',\), \(0,\)\)",
... repr(getting_started3.world('Hello').__reduce__()))
>>>
>>> for number in (24, 42):
... wd = getting_started3.world('California')
... wd.set_secret_number(number)
... pstr = pickle.dumps(wd)
... print pstr
... wl = pickle.loads(pstr)
... print wd.greet(), wd.get_secret_number()
... print wl.greet(), wl.get_secret_number()
cgetting_started3
world
p0
(S'California'
p1
tp2
R(I24
tp3
bp4
.
Hello from California! 24
Hello from California! 24
cgetting_started3
world
p0
(S'California'
p1
tp2
R(I42
tp3
bp4
.
Hello from California! 42
Hello from California! 0
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started3
doctest.testmod(test_getting_started3)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,35 @@
r'''>>> import getting_started4
>>> v=getting_started4.vector_double()
>>> print v.as_tuple()
()
>>> v=getting_started4.vector_double(5)
>>> print v.as_tuple()
(0.0, 0.0, 0.0, 0.0, 0.0)
>>> print len(v)
5
>>> v=getting_started4.vector_double((3,4,5))
>>> print v.as_tuple()
(3.0, 4.0, 5.0)
>>> print v[1]
4.0
>>> v[1] = 40
>>> print v.as_tuple()
(3.0, 40.0, 5.0)
>>> del v[1]
>>> print v.as_tuple()
(3.0, 5.0)
>>> print getting_started4.foo(11).as_tuple()
(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
>>> print getting_started4.bar(12).as_tuple()
(0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0)
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started4
doctest.testmod(test_getting_started4)
if __name__ == '__main__':
run()

View File

@@ -0,0 +1,22 @@
r'''>>> import getting_started5
>>> ixset = getting_started5.IndexingSet()
>>> ixset.add((1,2,3))
>>> ixset.add((4,5,6))
>>> ixset.add((7,8,9))
>>> print ixset.get(0)
(1, 2, 3)
>>> print ixset.get(1)
(4, 5, 6)
>>> print ixset.get(2)
(7, 8, 9)
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started5
doctest.testmod(test_getting_started5)
if __name__ == '__main__':
run()