mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 18:12:43 +00:00
This commit was manufactured by cvs2svn to create tag
'before_adding_complex'. [SVN r9301]
This commit is contained in:
34
example/abstract.cpp
Normal file
34
example/abstract.cpp
Normal 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");
|
||||
}
|
||||
69
example/dvect.cpp
Normal file
69
example/dvect.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "ivect.h"
|
||||
#include "dvect.h"
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace {
|
||||
|
||||
vects::ivect dvect_as_ivect(const vects::dvect& dv)
|
||||
{
|
||||
vects::ivect iv(dv.size());
|
||||
vects::ivect::iterator iviter = iv.begin();
|
||||
for (int i = 0; i < dv.size(); i++) iviter[i] = static_cast<int>(dv[i]);
|
||||
return iv;
|
||||
}
|
||||
|
||||
boost::python::tuple ivect_as_tuple(const vects::ivect& iv)
|
||||
{
|
||||
return iv.as_tuple();
|
||||
}
|
||||
|
||||
std::auto_ptr<vects::ivect> auto_ptr_ivect(const vects::dvect& dv)
|
||||
{
|
||||
return std::auto_ptr<vects::ivect>(new vects::ivect(dvect_as_ivect(dv)));
|
||||
}
|
||||
|
||||
boost::shared_ptr<vects::ivect> shared_ptr_ivect(const vects::dvect& dv)
|
||||
{
|
||||
return boost::shared_ptr<vects::ivect>(new vects::ivect(dvect_as_ivect(dv)));
|
||||
}
|
||||
|
||||
boost::python::tuple auto_ptr_ivect_as_tuple(std::auto_ptr<vects::ivect>& iv)
|
||||
{
|
||||
return iv->as_tuple();
|
||||
}
|
||||
|
||||
boost::python::tuple shared_ptr_ivect_as_tuple(boost::shared_ptr<vects::ivect>& iv)
|
||||
{
|
||||
return iv->as_tuple();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initdvect()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("dvect");
|
||||
|
||||
python::x_class_builder<vects::dvect> dvect_class(this_module, "dvect");
|
||||
|
||||
python::import_class_builder<vects::ivect> ivect_class("ivect", "ivect");
|
||||
|
||||
dvect_class.def(python::constructor<python::tuple>());
|
||||
dvect_class.def(&vects::dvect::as_tuple, "as_tuple");
|
||||
dvect_class.def(dvect_as_ivect, "as_ivect");
|
||||
|
||||
this_module.def(ivect_as_tuple, "ivect_as_tuple");
|
||||
dvect_class.def(auto_ptr_ivect, "auto_ptr_ivect");
|
||||
dvect_class.def(shared_ptr_ivect, "shared_ptr_ivect");
|
||||
this_module.def(auto_ptr_ivect_as_tuple, "auto_ptr_ivect_as_tuple");
|
||||
this_module.def(shared_ptr_ivect_as_tuple, "shared_ptr_ivect_as_tuple");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
32
example/dvect.h
Normal file
32
example/dvect.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef DVECT_H
|
||||
#define DVECT_H
|
||||
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace vects {
|
||||
|
||||
struct dvect : public std::vector<double>
|
||||
{
|
||||
dvect() : std::vector<double>() {}
|
||||
dvect(size_t n) : std::vector<double>(n) {}
|
||||
dvect(boost::python::tuple tuple) : std::vector<double>(tuple.size())
|
||||
{
|
||||
std::vector<double>::iterator v_it = begin();
|
||||
for (int i = 0; i < tuple.size(); i++)
|
||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
boost::python::type<double>());
|
||||
}
|
||||
|
||||
boost::python::tuple as_tuple() const
|
||||
{
|
||||
boost::python::tuple t(size());
|
||||
for (int i = 0; i < size(); i++)
|
||||
t.set_item(i,
|
||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DVECT_H
|
||||
@@ -1,54 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
namespace hello {
|
||||
class world
|
||||
{
|
||||
public:
|
||||
world(int) {}
|
||||
~world() {}
|
||||
const char* get() const { return "hi, world"; }
|
||||
};
|
||||
|
||||
size_t length(const world& x) { return strlen(x.get()); }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
// Python requires an exported function called init<module-name> 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
|
||||
boost::python::module_builder hello("hello");
|
||||
|
||||
// Create the Python type object for our extension class
|
||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
||||
|
||||
// Add the __init__ function
|
||||
world_class.def(boost::python::constructor<int>());
|
||||
// Add a regular member function
|
||||
world_class.def(&hello::world::get, "get");
|
||||
|
||||
// Add a regular function to the module
|
||||
hello.def(hello::length, "length");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif // _WIN32
|
||||
@@ -8,21 +8,18 @@ namespace { // Avoid cluttering the global namespace.
|
||||
}
|
||||
|
||||
#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"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void initrwgk1()
|
||||
DL_EXPORT(void)
|
||||
initgetting_started1()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("rwgk1");
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
@@ -33,9 +30,3 @@ void initrwgk1()
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
|
||||
#endif // _WIN32
|
||||
51
example/getting_started2.cpp
Normal file
51
example/getting_started2.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
122
example/getting_started3.cpp
Normal file
122
example/getting_started3.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
104
example/getting_started4.cpp
Normal file
104
example/getting_started4.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
128
example/getting_started5.cpp
Normal file
128
example/getting_started5.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
This example shows how to convert a class from and to native
|
||||
Python objects, such as tuples.
|
||||
|
||||
We do not want to expose the helper class MillerIndex as an
|
||||
Extension Class. However, in order to simplify the wrapper code,
|
||||
we want to define from_python() and to_python() functions for
|
||||
class MillerIndex.
|
||||
|
||||
Consider the alternatives:
|
||||
|
||||
- Expose MillerIndex as an Extension Class.
|
||||
We need a constructor MillerIndex(python::tuple).
|
||||
Python function calls become more complex:
|
||||
foo(MillerIndex((1,2,3)) instead of foo((1,2,3))
|
||||
We need a method such as MillerIndex().as_tuple().
|
||||
|
||||
- Define a wrapper function for each function that we
|
||||
want to expose, e.g.:
|
||||
void add(const IndexingSet& ixset, const python::tuple PyMIx)
|
||||
|
||||
The first alternative introduces a new type that the user has to
|
||||
deal with. Other modules using Miller indices might organize them in
|
||||
different ways, for example to increase runtime efficiency for
|
||||
important procedures. This means, the user has to know how to
|
||||
convert between the different kinds of Miller index representations.
|
||||
This can quickly become a nuisance. Relying on native Python data
|
||||
structures minimizes the number of special types the user has to
|
||||
learn and convert. Of course, this argument is only valid for
|
||||
small and relatively simply classes.
|
||||
|
||||
If there are many member functions with MillerIndex arguments, the
|
||||
second alternative is impractical, and concentrating the conversion
|
||||
mechanism in one central place is essential for code
|
||||
maintainability. An added benefit is that more convenient (smarter)
|
||||
conversion functions can be provided without cluttering the rest of
|
||||
the wrapper code.
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// The helper class.
|
||||
//
|
||||
class MillerIndex {
|
||||
public:
|
||||
int v[3];
|
||||
};
|
||||
|
||||
// The main class. Imagine that there are MANY member functions
|
||||
// like add() and get().
|
||||
//
|
||||
class IndexingSet {
|
||||
private:
|
||||
std::vector<MillerIndex> VMIx;
|
||||
public:
|
||||
void add(const MillerIndex& MIx) { VMIx.push_back(MIx); }
|
||||
MillerIndex get(const std::size_t i) const { return VMIx[i]; }
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
// Convert a Python tuple to a MillerIndex object.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<const MillerIndex&>)
|
||||
{
|
||||
python::tuple tup
|
||||
= python::tuple(python::ref(p, python::ref::increment_count));
|
||||
if (tup.size() != 3) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"expecting exactly 3 values in tuple.");
|
||||
throw python::error_already_set();
|
||||
}
|
||||
MillerIndex result;
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.v[i] = from_python(tup[i].get(), python::type<int>());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Similar conversion for MillerIndex objects passed by value.
|
||||
// Not actually used, but included to show the principle.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<MillerIndex>)
|
||||
{
|
||||
return from_python(p, python::type<const MillerIndex&>());
|
||||
}
|
||||
|
||||
// Convert a MillerIndex object to a Python tuple.
|
||||
//
|
||||
PyObject* to_python(const MillerIndex& hkl)
|
||||
{
|
||||
python::tuple result(3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.set_item(i, to_python(hkl.v[i]));
|
||||
return result.reference().release();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initgetting_started5()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started5");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<IndexingSet> ixset_class(this_module, "IndexingSet");
|
||||
|
||||
// Add the __init__ function.
|
||||
ixset_class.def(python::constructor<>());
|
||||
// Add the member functions.
|
||||
ixset_class.def(&IndexingSet::add, "add");
|
||||
ixset_class.def(&IndexingSet::get, "get");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
69
example/ivect.cpp
Normal file
69
example/ivect.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "ivect.h"
|
||||
#include "dvect.h"
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace {
|
||||
|
||||
vects::dvect ivect_as_dvect(const vects::ivect& iv)
|
||||
{
|
||||
vects::dvect dv(iv.size());
|
||||
vects::dvect::iterator dviter = dv.begin();
|
||||
for (int i = 0; i < iv.size(); i++) dviter[i] = static_cast<double>(iv[i]);
|
||||
return dv;
|
||||
}
|
||||
|
||||
boost::python::tuple dvect_as_tuple(const vects::dvect& dv)
|
||||
{
|
||||
return dv.as_tuple();
|
||||
}
|
||||
|
||||
std::auto_ptr<vects::dvect> auto_ptr_dvect(const vects::ivect& iv)
|
||||
{
|
||||
return std::auto_ptr<vects::dvect>(new vects::dvect(ivect_as_dvect(iv)));
|
||||
}
|
||||
|
||||
boost::shared_ptr<vects::dvect> shared_ptr_dvect(const vects::ivect& iv)
|
||||
{
|
||||
return boost::shared_ptr<vects::dvect>(new vects::dvect(ivect_as_dvect(iv)));
|
||||
}
|
||||
|
||||
boost::python::tuple auto_ptr_dvect_as_tuple(std::auto_ptr<vects::dvect>& dv)
|
||||
{
|
||||
return dv->as_tuple();
|
||||
}
|
||||
|
||||
boost::python::tuple shared_ptr_dvect_as_tuple(boost::shared_ptr<vects::dvect>& dv)
|
||||
{
|
||||
return dv->as_tuple();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initivect()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("ivect");
|
||||
|
||||
python::x_class_builder<vects::ivect> ivect_class(this_module, "ivect");
|
||||
|
||||
python::import_class_builder<vects::dvect> dvect_class("dvect", "dvect");
|
||||
|
||||
ivect_class.def(python::constructor<python::tuple>());
|
||||
ivect_class.def(&vects::ivect::as_tuple, "as_tuple");
|
||||
ivect_class.def(ivect_as_dvect, "as_dvect");
|
||||
|
||||
this_module.def(dvect_as_tuple, "dvect_as_tuple");
|
||||
ivect_class.def(auto_ptr_dvect, "auto_ptr_dvect");
|
||||
ivect_class.def(shared_ptr_dvect, "shared_ptr_dvect");
|
||||
this_module.def(auto_ptr_dvect_as_tuple, "auto_ptr_dvect_as_tuple");
|
||||
this_module.def(shared_ptr_dvect_as_tuple, "shared_ptr_dvect_as_tuple");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
32
example/ivect.h
Normal file
32
example/ivect.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef IVECT_H
|
||||
#define IVECT_H
|
||||
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace vects {
|
||||
|
||||
struct ivect : public std::vector<int>
|
||||
{
|
||||
ivect() : std::vector<int>() {}
|
||||
ivect(size_t n) : std::vector<int>(n) {}
|
||||
ivect(boost::python::tuple tuple) : std::vector<int>(tuple.size())
|
||||
{
|
||||
std::vector<int>::iterator v_it = begin();
|
||||
for (int i = 0; i < tuple.size(); i++)
|
||||
v_it[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
boost::python::type<int>());
|
||||
}
|
||||
|
||||
boost::python::tuple as_tuple() const
|
||||
{
|
||||
boost::python::tuple t(size());
|
||||
for (int i = 0; i < size(); i++)
|
||||
t.set_item(i,
|
||||
boost::python::ref(BOOST_PYTHON_CONVERSION::to_python((*this)[i])));
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // IVECT_H
|
||||
24
example/noncopyable_export.cpp
Normal file
24
example/noncopyable_export.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
#include "store.h"
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initnoncopyable_export()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("noncopyable_export");
|
||||
|
||||
python::xptr_class_builder<store> store_class(this_module, "store");
|
||||
|
||||
store_class.def(python::constructor<int>());
|
||||
store_class.def(&store::recall, "recall");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
42
example/noncopyable_import.cpp
Normal file
42
example/noncopyable_import.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <boost/python/class_builder.hpp>
|
||||
#include <boost/python/detail/import_extension_class.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
#include "store.h"
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A function with store objects as both input and output parameters.
|
||||
// Because the copy constructor is disabled, we cannot pass a store
|
||||
// object by value. Instead, we pass a smart pointer.
|
||||
std::auto_ptr<store> add_stores(const store& s1, const store& s2)
|
||||
{
|
||||
int sum = s1.recall() + s2.recall();
|
||||
std::auto_ptr<store> ss = std::auto_ptr<store>(new store(sum));
|
||||
return ss;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initnoncopyable_import()
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("noncopyable_import");
|
||||
|
||||
python::import_class_builder<store>
|
||||
dvect_class("noncopyable_export", "store");
|
||||
|
||||
// Imagine all the additional classes with member functions
|
||||
// that have store objects as input and output parameters.
|
||||
// Lots and lots of them.
|
||||
// However, to keep this example simple, we only define a
|
||||
// module-level function.
|
||||
this_module.def(add_stores, "add_stores");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
52
example/passing_char.cpp
Normal file
52
example/passing_char.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <iostream>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// In C++, char, signed char and unsigned char are three distinct types.
|
||||
// The Boost Python Library maps signed & unsigned char to
|
||||
// Python integers. Plain char is mapped to a Python string with
|
||||
// exactly one character.
|
||||
|
||||
// Plain char.
|
||||
char get_char() { return 'ÿ'; }
|
||||
void use_char(char c) {
|
||||
std::cout << c << std::endl;
|
||||
}
|
||||
|
||||
// signed char.
|
||||
signed char get_signed_char() { return -128; }
|
||||
void use_signed_char(signed char c) {
|
||||
std::cout << c << " " << static_cast<int>(c) << std::endl;
|
||||
}
|
||||
|
||||
// unsigned char.
|
||||
unsigned char get_unsigned_char() { return 128; }
|
||||
void use_unsigned_char(unsigned char c) {
|
||||
std::cout << c << " " << static_cast<unsigned int>(c) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initpassing_char()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("passing_char");
|
||||
|
||||
this_module.def(get_char, "get_char");
|
||||
this_module.def(use_char, "use_char");
|
||||
this_module.def(get_signed_char, "get_signed_char");
|
||||
this_module.def(use_signed_char, "use_signed_char");
|
||||
this_module.def(get_unsigned_char, "get_unsigned_char");
|
||||
this_module.def(use_unsigned_char, "use_unsigned_char");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
14
example/store.h
Normal file
14
example/store.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef STORE_H
|
||||
#define STORE_H
|
||||
|
||||
class store
|
||||
{
|
||||
private:
|
||||
store(const store&) { } // Disable the copy constructor.
|
||||
int number;
|
||||
public:
|
||||
store(const int i) : number(i) { }
|
||||
int recall() const { return number; }
|
||||
};
|
||||
|
||||
#endif // STORE_H
|
||||
23
example/test_abstract.py
Normal file
23
example/test_abstract.py
Normal 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()
|
||||
@@ -1,50 +0,0 @@
|
||||
r'''
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
That's it! If we build this shared library and put it on our PYTHONPATH we can
|
||||
now access our C++ class and function from Python.
|
||||
|
||||
>>> import hello
|
||||
>>> hi_world = hello.world(3)
|
||||
>>> hi_world.get()
|
||||
'hi, world'
|
||||
>>> hello.length(hi_world)
|
||||
9
|
||||
|
||||
We can even make a subclass of hello.world:
|
||||
|
||||
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> y = my_subclass(2)
|
||||
>>> y.get()
|
||||
'hello, world'
|
||||
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
|
||||
>>> hello.length(y)
|
||||
9
|
||||
|
||||
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 length() of
|
||||
12? If so, read on...
|
||||
'''
|
||||
from hello import *
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_example1
|
||||
doctest.testmod(test_example1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
17
example/test_getting_started1.py
Normal file
17
example/test_getting_started1.py
Normal 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()
|
||||
19
example/test_getting_started2.py
Normal file
19
example/test_getting_started2.py
Normal 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()
|
||||
56
example/test_getting_started3.py
Normal file
56
example/test_getting_started3.py
Normal 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()
|
||||
35
example/test_getting_started4.py
Normal file
35
example/test_getting_started4.py
Normal 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()
|
||||
22
example/test_getting_started5.py
Normal file
22
example/test_getting_started5.py
Normal 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()
|
||||
@@ -1,17 +0,0 @@
|
||||
r'''>>> import rwgk1
|
||||
>>> print rwgk1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', rwgk1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_rwgk1
|
||||
doctest.testmod(test_rwgk1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
16
example/tst_dvect.py
Normal file
16
example/tst_dvect.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import dvect
|
||||
print dvect.dvect.__converters__
|
||||
dv = dvect.dvect((1,2,3,4,5))
|
||||
print dv
|
||||
print dv.as_tuple()
|
||||
iv = dv.as_ivect()
|
||||
print iv
|
||||
print iv.as_tuple()
|
||||
print dvect.ivect_as_tuple(iv)
|
||||
aiv = dv.auto_ptr_ivect()
|
||||
print aiv
|
||||
siv = dv.shared_ptr_ivect()
|
||||
print dvect.auto_ptr_ivect_as_tuple(aiv)
|
||||
print dvect.ivect_as_tuple(aiv)
|
||||
print dvect.shared_ptr_ivect_as_tuple(siv)
|
||||
print dvect.ivect_as_tuple(siv)
|
||||
16
example/tst_ivect.py
Normal file
16
example/tst_ivect.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import ivect
|
||||
print ivect.ivect.__converters__
|
||||
iv = ivect.ivect((1,2,3,4,5))
|
||||
print iv
|
||||
print iv.as_tuple()
|
||||
dv = iv.as_dvect()
|
||||
print dv
|
||||
print dv.as_tuple()
|
||||
print ivect.dvect_as_tuple(dv)
|
||||
adv = iv.auto_ptr_dvect()
|
||||
print adv
|
||||
sdv = iv.shared_ptr_dvect()
|
||||
print ivect.auto_ptr_dvect_as_tuple(adv)
|
||||
print ivect.dvect_as_tuple(adv)
|
||||
print ivect.shared_ptr_dvect_as_tuple(sdv)
|
||||
print ivect.dvect_as_tuple(sdv)
|
||||
8
example/tst_noncopyable.py
Normal file
8
example/tst_noncopyable.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import noncopyable_export
|
||||
import noncopyable_import
|
||||
s1 = noncopyable_export.store(1)
|
||||
print s1.recall()
|
||||
s2 = noncopyable_export.store(2)
|
||||
print s2.recall()
|
||||
s3 = noncopyable_import.add_stores(s1, s2)
|
||||
print s3.recall()
|
||||
20
example/tst_passing_char.py
Normal file
20
example/tst_passing_char.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import passing_char
|
||||
print passing_char.get_char()
|
||||
print passing_char.get_signed_char()
|
||||
print passing_char.get_unsigned_char()
|
||||
for arg in (-97, 97, -140, 140, "a", "ab"):
|
||||
try:
|
||||
print 'char', arg, ':'
|
||||
passing_char.use_char(arg)
|
||||
except (TypeError, ValueError), e:
|
||||
print e.args[0]
|
||||
try:
|
||||
print 'signed char', arg, ':'
|
||||
passing_char.use_signed_char(arg)
|
||||
except (TypeError, ValueError), e:
|
||||
print e.args[0]
|
||||
try:
|
||||
print 'unsigned char', arg, ':'
|
||||
passing_char.use_unsigned_char(arg)
|
||||
except (TypeError, ValueError), e:
|
||||
print e.args[0]
|
||||
Reference in New Issue
Block a user