summaryrefslogtreecommitdiffstats
path: root/lib/kross/python/cxx
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /lib/kross/python/cxx
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/kross/python/cxx')
-rw-r--r--lib/kross/python/cxx/Config.hxx74
-rw-r--r--lib/kross/python/cxx/Exception.hxx212
-rw-r--r--lib/kross/python/cxx/Extensions.hxx756
-rw-r--r--lib/kross/python/cxx/IndirectPythonInterface.cxx550
-rw-r--r--lib/kross/python/cxx/IndirectPythonInterface.hxx156
-rwxr-xr-xlib/kross/python/cxx/Legal.html40
-rw-r--r--lib/kross/python/cxx/Makefile.am19
-rw-r--r--lib/kross/python/cxx/Objects.hxx2804
-rw-r--r--lib/kross/python/cxx/PyCXX.html2131
-rw-r--r--lib/kross/python/cxx/README.html436
-rw-r--r--lib/kross/python/cxx/Readme.Kross.txt16
-rw-r--r--lib/kross/python/cxx/Version.txt1
-rw-r--r--lib/kross/python/cxx/cxx_extensions.cxx1287
-rw-r--r--lib/kross/python/cxx/cxxextensions.c19
-rw-r--r--lib/kross/python/cxx/cxxsupport.cxx142
15 files changed, 8643 insertions, 0 deletions
diff --git a/lib/kross/python/cxx/Config.hxx b/lib/kross/python/cxx/Config.hxx
new file mode 100644
index 00000000..65bbc2d3
--- /dev/null
+++ b/lib/kross/python/cxx/Config.hxx
@@ -0,0 +1,74 @@
+#ifndef __PyCXX_config_hh__
+#define __PyCXX_config_hh__
+
+//
+// Microsoft VC++ 6.0 has no traits
+//
+#if defined( _MSC_VER )
+
+# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1
+
+#elif defined( __GNUC__ )
+# if __GNUC__ >= 3
+# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1
+# else
+# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 0
+#endif
+
+//
+// Assume all other compilers do
+//
+#else
+
+// Macros to deal with deficiencies in compilers
+# define STANDARD_LIBRARY_HAS_ITERATOR_TRAITS 1
+#endif
+
+#if STANDARD_LIBRARY_HAS_ITERATOR_TRAITS
+# define random_access_iterator_parent(itemtype) std::iterator<std::random_access_iterator_tag,itemtype,int>
+#else
+# define random_access_iterator_parent(itemtype) std::random_access_iterator<itemtype, int>
+#endif
+
+//
+// Which C++ standard is in use?
+//
+#if defined( _MSC_VER )
+# if _MSC_VER <= 1200
+// MSVC++ 6.0
+# define PYCXX_ISO_CPP_LIB 0
+# define STR_STREAM <strstream>
+# define TEMPLATE_TYPENAME class
+# else
+# define PYCXX_ISO_CPP_LIB 1
+# define STR_STREAM <sstream>
+# define TEMPLATE_TYPENAME typename
+# endif
+#elif defined( __GNUC__ )
+# if __GNUC__ >= 3
+# define PYCXX_ISO_CPP_LIB 1
+# define STR_STREAM <sstream>
+# define TEMPLATE_TYPENAME typename
+# else
+# define PYCXX_ISO_CPP_LIB 0
+# define STR_STREAM <strstream>
+# define TEMPLATE_TYPENAME class
+# endif
+#endif
+
+#if PYCXX_ISO_CPP_LIB
+# define STR_STREAM <sstream>
+# define OSTRSTREAM ostringstream
+# define EXPLICIT_TYPENAME typename
+# define EXPLICIT_CLASS class
+# define TEMPLATE_TYPENAME typename
+#else
+# define STR_STREAM <strstream>
+# define OSTRSTREAM ostrstream
+# define EXPLICIT_TYPENAME
+# define EXPLICIT_CLASS
+# define TEMPLATE_TYPENAME class
+#endif
+
+
+#endif // __PyCXX_config_hh__
diff --git a/lib/kross/python/cxx/Exception.hxx b/lib/kross/python/cxx/Exception.hxx
new file mode 100644
index 00000000..afcff489
--- /dev/null
+++ b/lib/kross/python/cxx/Exception.hxx
@@ -0,0 +1,212 @@
+//----------------------------------*-C++-*----------------------------------//
+// Copyright 1998 The Regents of the University of California.
+// All rights reserved. See LEGAL.LLNL for full text and disclaimer.
+//---------------------------------------------------------------------------//
+
+#ifndef __CXX_Exception_h
+#define __CXX_Exception_h
+
+#include "Python.h"
+#include "Config.hxx"
+#include "IndirectPythonInterface.hxx"
+
+#include <string>
+#include <iostream>
+
+// This mimics the Python structure, in order to minimize confusion
+namespace Py
+ {
+ class ExtensionExceptionType;
+
+ class Exception
+ {
+ public:
+ Exception( ExtensionExceptionType &exception, const std::string& reason );
+
+ explicit Exception ()
+ {}
+
+ Exception (const std::string& reason)
+ {
+ PyErr_SetString (Py::_Exc_RuntimeError(), reason.c_str());
+ }
+
+ Exception (PyObject* exception, const std::string& reason)
+ {
+ PyErr_SetString (exception, reason.c_str());
+ }
+
+
+ void clear() // clear the error
+ // technically but not philosophically const
+ {
+ PyErr_Clear();
+ }
+ };
+
+
+ // Abstract
+ class StandardError: public Exception
+ {
+ protected:
+ explicit StandardError()
+ {}
+ };
+
+ class LookupError: public StandardError
+ {
+ protected:
+ explicit LookupError()
+ {}
+ };
+
+ class ArithmeticError: public StandardError
+ {
+ protected:
+ explicit ArithmeticError()
+ {}
+ };
+
+ class EnvironmentError: public StandardError
+ {
+ protected:
+ explicit EnvironmentError()
+ {}
+ };
+
+ // Concrete
+
+ class TypeError: public StandardError
+ {
+ public:
+ TypeError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_TypeError(),reason.c_str());
+ }
+ };
+
+ class IndexError: public LookupError
+ {
+ public:
+ IndexError (const std::string& reason)
+ : LookupError()
+ {
+ PyErr_SetString (Py::_Exc_IndexError(), reason.c_str());
+ }
+ };
+
+ class AttributeError: public StandardError
+ {
+ public:
+ AttributeError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_AttributeError(), reason.c_str());
+ }
+ };
+
+ class NameError: public StandardError
+ {
+ public:
+ NameError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_NameError(), reason.c_str());
+ }
+ };
+
+ class RuntimeError: public StandardError
+ {
+ public:
+ RuntimeError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_RuntimeError(), reason.c_str());
+ }
+ };
+
+ class SystemError: public StandardError
+ {
+ public:
+ SystemError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_SystemError(),reason.c_str());
+ }
+ };
+
+ class KeyError: public LookupError
+ {
+ public:
+ KeyError (const std::string& reason)
+ : LookupError()
+ {
+ PyErr_SetString (Py::_Exc_KeyError(),reason.c_str());
+ }
+ };
+
+
+ class ValueError: public StandardError
+ {
+ public:
+ ValueError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_ValueError(), reason.c_str());
+ }
+ };
+
+ class OverflowError: public ArithmeticError
+ {
+ public:
+ OverflowError (const std::string& reason)
+ : ArithmeticError()
+ {
+ PyErr_SetString (Py::_Exc_OverflowError(), reason.c_str());
+ }
+ };
+
+ class ZeroDivisionError: public ArithmeticError
+ {
+ public:
+ ZeroDivisionError (const std::string& reason)
+ : ArithmeticError()
+ {
+ PyErr_SetString (Py::_Exc_ZeroDivisionError(), reason.c_str());
+ }
+ };
+
+ class FloatingPointError: public ArithmeticError
+ {
+ public:
+ FloatingPointError (const std::string& reason)
+ : ArithmeticError()
+ {
+ PyErr_SetString (Py::_Exc_FloatingPointError(), reason.c_str());
+ }
+ };
+
+ class MemoryError: public StandardError
+ {
+ public:
+ MemoryError (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_MemoryError(), reason.c_str());
+ }
+ };
+
+ class SystemExit: public StandardError
+ {
+ public:
+ SystemExit (const std::string& reason)
+ : StandardError()
+ {
+ PyErr_SetString (Py::_Exc_SystemExit(),reason.c_str());
+ }
+ };
+
+ }// Py
+
+#endif
diff --git a/lib/kross/python/cxx/Extensions.hxx b/lib/kross/python/cxx/Extensions.hxx
new file mode 100644
index 00000000..69ce9a14
--- /dev/null
+++ b/lib/kross/python/cxx/Extensions.hxx
@@ -0,0 +1,756 @@
+//----------------------------------*-C++-*----------------------------------//
+// Copyright 1998 The Regents of the University of California.
+// All rights reserved. See LEGAL.LLNL for full text and disclaimer.
+//---------------------------------------------------------------------------//
+
+#ifndef __CXX_Extensions__h
+#define __CXX_Extensions__h
+
+
+#ifdef _MSC_VER
+// disable warning C4786: symbol greater than 255 character,
+// okay to ignore
+#pragma warning(disable: 4786)
+#endif
+
+
+#include "Config.hxx"
+#include "Objects.hxx"
+
+extern "C"
+ {
+ extern PyObject py_object_initializer;
+ }
+
+#include <vector>
+#include <map>
+
+namespace Py
+ {
+ class ExtensionModuleBase;
+
+ // Make an Exception Type for use in raising custom exceptions
+ class ExtensionExceptionType : public Object
+ {
+ public:
+ ExtensionExceptionType();
+ virtual ~ExtensionExceptionType();
+
+ // call init to create the type
+ void init( ExtensionModuleBase &module, const std::string& name );
+ };
+
+
+ class MethodTable
+ {
+ public:
+ MethodTable();
+ virtual ~MethodTable();
+
+ void add(const char* method_name, PyCFunction f, const char* doc="", int flag=1);
+ PyMethodDef* table();
+
+ protected:
+ std::vector<PyMethodDef> t; // accumulator of PyMethodDef's
+ PyMethodDef *mt; // Actual method table produced when full
+
+ static PyMethodDef method (const char* method_name, PyCFunction f, int flags = 1, const char* doc="");
+
+ private:
+ //
+ // prevent the compiler generating these unwanted functions
+ //
+ MethodTable(const MethodTable& m); //unimplemented
+ void operator=(const MethodTable& m); //unimplemented
+
+ }; // end class MethodTable
+
+ extern "C"
+ {
+ typedef PyObject *(*method_varargs_call_handler_t)( PyObject *_self, PyObject *_args );
+ typedef PyObject *(*method_keyword_call_handler_t)( PyObject *_self, PyObject *_args, PyObject *_dict );
+ }
+
+ template<class T>
+ class MethodDefExt : public PyMethodDef
+ {
+ public:
+ typedef Object (T::*method_varargs_function_t)( const Tuple &args );
+ typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
+
+ MethodDefExt
+ (
+ const char *_name,
+ method_varargs_function_t _function,
+ method_varargs_call_handler_t _handler,
+ const char *_doc
+ )
+ {
+ ext_meth_def.ml_name = const_cast<char *>(_name);
+ ext_meth_def.ml_meth = _handler;
+ ext_meth_def.ml_flags = METH_VARARGS;
+ ext_meth_def.ml_doc = const_cast<char *>(_doc);
+
+ ext_varargs_function = _function;
+ ext_keyword_function = NULL;
+ }
+
+ MethodDefExt
+ (
+ const char *_name,
+ method_keyword_function_t _function,
+ method_keyword_call_handler_t _handler,
+ const char *_doc
+ )
+ {
+ ext_meth_def.ml_name = const_cast<char *>(_name);
+ ext_meth_def.ml_meth = method_varargs_call_handler_t( _handler );
+ ext_meth_def.ml_flags = METH_VARARGS|METH_KEYWORDS;
+ ext_meth_def.ml_doc = const_cast<char *>(_doc);
+
+ ext_varargs_function = NULL;
+ ext_keyword_function = _function;
+ }
+
+ ~MethodDefExt()
+ {}
+
+ PyMethodDef ext_meth_def;
+ method_varargs_function_t ext_varargs_function;
+ method_keyword_function_t ext_keyword_function;
+ };
+
+ class ExtensionModuleBase
+ {
+ public:
+ ExtensionModuleBase( const char *name );
+ virtual ~ExtensionModuleBase();
+
+ Module module(void) const; // only valid after initialize() has been called
+ Dict moduleDictionary(void) const; // only valid after initialize() has been called
+
+ virtual Object invoke_method_keyword( const std::string &_name, const Tuple &_args, const Dict &_keywords ) = 0;
+ virtual Object invoke_method_varargs( const std::string &_name, const Tuple &_args ) = 0;
+
+ const std::string &name() const;
+ const std::string &fullName() const;
+
+ protected:
+ // Initialize the module
+ void initialize( const char *module_doc );
+
+ const std::string module_name;
+ const std::string full_module_name;
+ MethodTable method_table;
+
+ private:
+
+ //
+ // prevent the compiler generating these unwanted functions
+ //
+ ExtensionModuleBase( const ExtensionModuleBase & ); //unimplemented
+ void operator=( const ExtensionModuleBase & ); //unimplemented
+
+ };
+
+ extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords );
+ extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args );
+ extern "C" void do_not_dealloc( void * );
+
+
+ template<TEMPLATE_TYPENAME T>
+ class ExtensionModule : public ExtensionModuleBase
+ {
+ public:
+ ExtensionModule( const char *name )
+ : ExtensionModuleBase( name )
+ {}
+ virtual ~ExtensionModule()
+ {}
+
+ protected:
+ typedef Object (T::*method_varargs_function_t)( const Tuple &args );
+ typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
+ typedef std::map<std::string,MethodDefExt<T> *> method_map_t;
+
+ static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
+ {
+ method_map_t &mm = methods();
+
+ MethodDefExt<T> *method_definition = new MethodDefExt<T>
+ (
+ name,
+ function,
+ method_varargs_call_handler,
+ doc
+ );
+
+ mm[std::string( name )] = method_definition;
+ }
+
+ static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
+ {
+ method_map_t &mm = methods();
+
+ MethodDefExt<T> *method_definition = new MethodDefExt<T>
+ (
+ name,
+ function,
+ method_keyword_call_handler,
+ doc
+ );
+
+ mm[std::string( name )] = method_definition;
+ }
+
+ void initialize( const char *module_doc="" )
+ {
+ ExtensionModuleBase::initialize( module_doc );
+ Dict dict( moduleDictionary() );
+
+ //
+ // put each of the methods into the modules dictionary
+ // so that we get called back at the function in T.
+ //
+ method_map_t &mm = methods();
+ EXPLICIT_TYPENAME method_map_t::iterator i;
+
+ for( i=mm.begin(); i != mm.end(); ++i )
+ {
+ MethodDefExt<T> *method_definition = (*i).second;
+
+ static PyObject *self = PyCObject_FromVoidPtr( this, do_not_dealloc );
+
+ Tuple args( 2 );
+ args[0] = Object( self );
+ args[1] = String( (*i).first );
+
+ PyObject *func = PyCFunction_New
+ (
+ &method_definition->ext_meth_def,
+ new_reference_to( args )
+ );
+
+ dict[ (*i).first ] = Object( func );
+ }
+ }
+
+ protected: // Tom Malcolmson reports that derived classes need access to these
+
+ static method_map_t &methods(void)
+ {
+ static method_map_t *map_of_methods = NULL;
+ if( map_of_methods == NULL )
+ map_of_methods = new method_map_t;
+
+ return *map_of_methods;
+ }
+
+
+ // this invoke function must be called from within a try catch block
+ virtual Object invoke_method_keyword( const std::string &name, const Tuple &args, const Dict &keywords )
+ {
+ method_map_t &mm = methods();
+ MethodDefExt<T> *meth_def = mm[ name ];
+ if( meth_def == NULL )
+ {
+ std::string error_msg( "CXX - cannot invoke keyword method named " );
+ error_msg += name;
+ throw RuntimeError( error_msg );
+ }
+
+ // cast up to the derived class
+ T *self = static_cast<T *>(this);
+
+ return (self->*meth_def->ext_keyword_function)( args, keywords );
+ }
+
+ // this invoke function must be called from within a try catch block
+ virtual Object invoke_method_varargs( const std::string &name, const Tuple &args )
+ {
+ method_map_t &mm = methods();
+ MethodDefExt<T> *meth_def = mm[ name ];
+ if( meth_def == NULL )
+ {
+ std::string error_msg( "CXX - cannot invoke varargs method named " );
+ error_msg += name;
+ throw RuntimeError( error_msg );
+ }
+
+ // cast up to the derived class
+ T *self = static_cast<T *>(this);
+
+ return (self->*meth_def->ext_varargs_function)( args );
+ }
+
+ private:
+ //
+ // prevent the compiler generating these unwanted functions
+ //
+ ExtensionModule( const ExtensionModule<T> & ); //unimplemented
+ void operator=( const ExtensionModule<T> & ); //unimplemented
+ };
+
+
+ class PythonType
+ {
+ public:
+ // if you define one sequence method you must define
+ // all of them except the assigns
+
+ PythonType (size_t base_size, int itemsize, const char *default_name );
+ virtual ~PythonType ();
+
+ const char *getName () const;
+ const char *getDoc () const;
+
+ PyTypeObject* type_object () const;
+ void name (const char* nam);
+ void doc (const char* d);
+ void dealloc(void (*f)(PyObject*));
+
+ void supportPrint(void);
+ void supportGetattr(void);
+ void supportSetattr(void);
+ void supportGetattro(void);
+ void supportSetattro(void);
+ void supportCompare(void);
+ void supportRepr(void);
+ void supportStr(void);
+ void supportHash(void);
+ void supportCall(void);
+
+ void supportSequenceType(void);
+ void supportMappingType(void);
+ void supportNumberType(void);
+ void supportBufferType(void);
+
+ protected:
+ PyTypeObject *table;
+ PySequenceMethods *sequence_table;
+ PyMappingMethods *mapping_table;
+ PyNumberMethods *number_table;
+ PyBufferProcs *buffer_table;
+
+ void init_sequence();
+ void init_mapping();
+ void init_number();
+ void init_buffer();
+
+ private:
+ //
+ // prevent the compiler generating these unwanted functions
+ //
+ PythonType (const PythonType& tb); // unimplemented
+ void operator=(const PythonType& t); // unimplemented
+
+ }; // end of PythonType
+
+
+
+ // Class PythonExtension is what you inherit from to create
+ // a new Python extension type. You give your class itself
+ // as the template paramter.
+
+ // There are two ways that extension objects can get destroyed.
+ // 1. Their reference count goes to zero
+ // 2. Someone does an explicit delete on a pointer.
+ // In (1) the problem is to get the destructor called
+ // We register a special deallocator in the Python type object
+ // (see behaviors()) to do this.
+ // In (2) there is no problem, the dtor gets called.
+
+ // PythonExtension does not use the usual Python heap allocator,
+ // instead using new/delete. We do the setting of the type object
+ // and reference count, usually done by PyObject_New, in the
+ // base class ctor.
+
+ // This special deallocator does a delete on the pointer.
+
+
+ class PythonExtensionBase : public PyObject
+ {
+ public:
+ PythonExtensionBase();
+ virtual ~PythonExtensionBase();
+
+ public:
+ virtual int print( FILE *, int );
+ virtual Object getattr( const char * ) = 0;
+ virtual int setattr( const char *, const Object & );
+ virtual Object getattro( const Object & );
+ virtual int setattro( const Object &, const Object & );
+ virtual int compare( const Object & );
+ virtual Object repr();
+ virtual Object str();
+ virtual long hash();
+ virtual Object call( const Object &, const Object & );
+
+ // Sequence methods
+ virtual int sequence_length();
+ virtual Object sequence_concat( const Object & );
+ virtual Object sequence_repeat( int );
+ virtual Object sequence_item( int );
+ virtual Object sequence_slice( int, int );
+ virtual int sequence_ass_item( int, const Object & );
+ virtual int sequence_ass_slice( int, int, const Object & );
+
+ // Mapping
+ virtual int mapping_length();
+ virtual Object mapping_subscript( const Object & );
+ virtual int mapping_ass_subscript( const Object &, const Object & );
+
+ // Number
+ virtual int number_nonzero();
+ virtual Object number_negative();
+ virtual Object number_positive();
+ virtual Object number_absolute();
+ virtual Object number_invert();
+ virtual Object number_int();
+ virtual Object number_float();
+ virtual Object number_long();
+ virtual Object number_oct();
+ virtual Object number_hex();
+ virtual Object number_add( const Object & );
+ virtual Object number_subtract( const Object & );
+ virtual Object number_multiply( const Object & );
+ virtual Object number_divide( const Object & );
+ virtual Object number_remainder( const Object & );
+ virtual Object number_divmod( const Object & );
+ virtual Object number_lshift( const Object & );
+ virtual Object number_rshift( const Object & );
+ virtual Object number_and( const Object & );
+ virtual Object number_xor( const Object & );
+ virtual Object number_or( const Object & );
+ virtual Object number_power( const Object &, const Object & );
+
+ // Buffer
+ virtual int buffer_getreadbuffer( int, void** );
+ virtual int buffer_getwritebuffer( int, void** );
+ virtual int buffer_getsegcount( int* );
+
+ private:
+ void missing_method( void );
+ static PyObject *method_call_handler( PyObject *self, PyObject *args );
+ };
+
+ template<TEMPLATE_TYPENAME T>
+ class PythonExtension: public PythonExtensionBase
+ {
+ public:
+ static PyTypeObject* type_object()
+ {
+ return behaviors().type_object();
+ }
+
+ static int check( PyObject *p )
+ {
+ // is p like me?
+ return p->ob_type == type_object();
+ }
+
+ static int check( const Object& ob )
+ {
+ return check( ob.ptr());
+ }
+
+
+ //
+ // every object needs getattr implemented
+ // to support methods
+ //
+ virtual Object getattr( const char *name )
+ {
+ return getattr_methods( name );
+ }
+
+ protected:
+ explicit PythonExtension()
+ : PythonExtensionBase()
+ {
+ #ifdef PyObject_INIT
+ (void)PyObject_INIT( this, type_object() );
+ #else
+ ob_refcnt = 1;
+ ob_type = type_object();
+ #endif
+
+ // every object must support getattr
+ behaviors().supportGetattr();
+ }
+
+ virtual ~PythonExtension()
+ {}
+
+ static PythonType &behaviors()
+ {
+ static PythonType* p;
+ if( p == NULL )
+ {
+#if defined( _CPPRTTI )
+ const char *default_name = (typeid ( T )).name();
+#else
+ const char *default_name = "unknown";
+#endif
+ p = new PythonType( sizeof( T ), 0, default_name );
+ p->dealloc( extension_object_deallocator );
+ }
+
+ return *p;
+ }
+
+
+ typedef Object (T::*method_varargs_function_t)( const Tuple &args );
+ typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
+ typedef std::map<std::string,MethodDefExt<T> *> method_map_t;
+
+ // support the default attributes, __name__, __doc__ and methods
+ virtual Object getattr_default( const char *_name )
+ {
+ std::string name( _name );
+
+ if( name == "__name__" && type_object()->tp_name != NULL )
+ {
+ return Py::String( type_object()->tp_name );
+ }
+ else if( name == "__doc__" && type_object()->tp_doc != NULL )
+ {
+ return Py::String( type_object()->tp_doc );
+ }
+
+// trying to fake out being a class for help()
+// else if( name == "__bases__" )
+// {
+// return Py::Tuple(0);
+// }
+// else if( name == "__module__" )
+// {
+// return Py::Nothing();
+// }
+// else if( name == "__dict__" )
+// {
+// return Py::Dict();
+// }
+ else
+ {
+ return getattr_methods( _name );
+ }
+ }
+
+ // turn a name into function object
+ virtual Object getattr_methods( const char *_name )
+ {
+ std::string name( _name );
+
+ method_map_t &mm = methods();
+
+ if( name == "__methods__" )
+ {
+ List methods;
+
+ for( EXPLICIT_TYPENAME method_map_t::iterator i = mm.begin(); i != mm.end(); ++i )
+ methods.append( String( (*i).first ) );
+
+ return methods;
+ }
+
+ // see if name exists
+ if( mm.find( name ) == mm.end() )
+ throw AttributeError( "method '" + name + "' does not exist." );
+
+ Tuple self( 2 );
+
+ self[0] = Object( this );
+ self[1] = String( name );
+
+ MethodDefExt<T> *method_definition = mm[ name ];
+
+ PyObject *func = PyCFunction_New( &method_definition->ext_meth_def, self.ptr() );
+
+ return Object(func, true);
+ }
+
+ static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
+ {
+ method_map_t &mm = methods();
+
+ MethodDefExt<T> *method_definition = new MethodDefExt<T>
+ (
+ name,
+ function,
+ method_varargs_call_handler,
+ doc
+ );
+
+ mm[std::string( name )] = method_definition;
+ }
+
+ static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
+ {
+ method_map_t &mm = methods();
+
+ MethodDefExt<T> *method_definition = new MethodDefExt<T>
+ (
+ name,
+ function,
+ method_keyword_call_handler,
+ doc
+ );
+
+ mm[std::string( name )] = method_definition;
+ }
+
+ private:
+ static method_map_t &methods(void)
+ {
+ static method_map_t *map_of_methods = NULL;
+ if( map_of_methods == NULL )
+ map_of_methods = new method_map_t;
+
+ return *map_of_methods;
+ }
+
+ static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords )
+ {
+ try
+ {
+ Tuple self_and_name_tuple( _self_and_name_tuple );
+
+ PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
+ T *self = static_cast<T *>( self_in_cobject );
+
+ String name( self_and_name_tuple[1] );
+
+ method_map_t &mm = methods();
+ MethodDefExt<T> *meth_def = mm[ name ];
+ if( meth_def == NULL )
+ return 0;
+
+ Tuple args( _args );
+
+ // _keywords may be NULL so be careful about the way the dict is created
+ Dict keywords;
+ if( _keywords != NULL )
+ keywords = Dict( _keywords );
+
+ Object result( (self->*meth_def->ext_keyword_function)( args, keywords ) );
+
+ return new_reference_to( result.ptr() );
+ }
+ catch( Exception & )
+ {
+ return 0;
+ }
+ }
+
+ static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args )
+ {
+ try
+ {
+ Tuple self_and_name_tuple( _self_and_name_tuple );
+
+ PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
+ T *self = static_cast<T *>( self_in_cobject );
+
+ String name( self_and_name_tuple[1] );
+
+ method_map_t &mm = methods();
+ MethodDefExt<T> *meth_def = mm[ name ];
+ if( meth_def == NULL )
+ return 0;
+
+ Tuple args( _args );
+
+ Object result;
+
+ // TMM: 7Jun'01 - Adding try & catch in case of STL debug-mode exceptions.
+ #ifdef _STLP_DEBUG
+ try
+ {
+ result = (self->*meth_def->ext_varargs_function)( args );
+ }
+ catch (std::__stl_debug_exception)
+ {
+ // throw cxx::RuntimeError( sErrMsg );
+ throw cxx::RuntimeError( "Error message not set yet." );
+ }
+ #else
+ result = (self->*meth_def->ext_varargs_function)( args );
+ #endif // _STLP_DEBUG
+
+ return new_reference_to( result.ptr() );
+ }
+ catch( Exception & )
+ {
+ return 0;
+ }
+ }
+
+ static void extension_object_deallocator ( PyObject* t )
+ {
+ delete (T *)( t );
+ }
+
+ //
+ // prevent the compiler generating these unwanted functions
+ //
+ explicit PythonExtension( const PythonExtension<T>& other );
+ void operator=( const PythonExtension<T>& rhs );
+ };
+
+ //
+ // ExtensionObject<T> is an Object that will accept only T's.
+ //
+ template<TEMPLATE_TYPENAME T>
+ class ExtensionObject: public Object
+ {
+ public:
+
+ explicit ExtensionObject ( PyObject *pyob )
+ : Object( pyob )
+ {
+ validate();
+ }
+
+ ExtensionObject( const ExtensionObject<T>& other )
+ : Object( *other )
+ {
+ validate();
+ }
+
+ ExtensionObject( const Object& other )
+ : Object( *other )
+ {
+ validate();
+ }
+
+ ExtensionObject& operator= ( const Object& rhs )
+ {
+ return (*this = *rhs );
+ }
+
+ ExtensionObject& operator= ( PyObject* rhsp )
+ {
+ if( ptr() == rhsp )
+ return *this;
+ set( rhsp );
+ return *this;
+ }
+
+ virtual bool accepts ( PyObject *pyob ) const
+ {
+ return ( pyob && T::check( pyob ));
+ }
+
+ //
+ // Obtain a pointer to the PythonExtension object
+ //
+ T *extensionObject(void)
+ {
+ return static_cast<T *>( ptr() );
+ }
+ };
+
+ } // Namespace Py
+// End of CXX_Extensions.h
+#endif
diff --git a/lib/kross/python/cxx/IndirectPythonInterface.cxx b/lib/kross/python/cxx/IndirectPythonInterface.cxx
new file mode 100644
index 00000000..caaa0913
--- /dev/null
+++ b/lib/kross/python/cxx/IndirectPythonInterface.cxx
@@ -0,0 +1,550 @@
+//
+// IndirectPythonInterface.cxx
+//
+#undef _XOPEN_SOURCE
+#include "IndirectPythonInterface.hxx"
+
+namespace Py
+{
+bool _Buffer_Check( PyObject *op ) { return (op)->ob_type == _Buffer_Type(); }
+bool _CFunction_Check( PyObject *op ) { return (op)->ob_type == _CFunction_Type(); }
+bool _Class_Check( PyObject *op ) { return (op)->ob_type == _Class_Type(); }
+bool _CObject_Check( PyObject *op ) { return (op)->ob_type == _CObject_Type(); }
+bool _Complex_Check( PyObject *op ) { return (op)->ob_type == _Complex_Type(); }
+bool _Dict_Check( PyObject *op ) { return (op)->ob_type == _Dict_Type(); }
+bool _File_Check( PyObject *op ) { return (op)->ob_type == _File_Type(); }
+bool _Float_Check( PyObject *op ) { return (op)->ob_type == _Float_Type(); }
+bool _Function_Check( PyObject *op ) { return (op)->ob_type == _Function_Type(); }
+bool _Instance_Check( PyObject *op ) { return (op)->ob_type == _Instance_Type(); }
+bool _Int_Check( PyObject *op ) { return (op)->ob_type == _Int_Type(); }
+bool _List_Check( PyObject *o ) { return o->ob_type == _List_Type(); }
+bool _Long_Check( PyObject *op ) { return (op)->ob_type == _Long_Type(); }
+bool _Method_Check( PyObject *op ) { return (op)->ob_type == _Method_Type(); }
+bool _Module_Check( PyObject *op ) { return (op)->ob_type == _Module_Type(); }
+bool _Range_Check( PyObject *op ) { return (op)->ob_type == _Range_Type(); }
+bool _Slice_Check( PyObject *op ) { return (op)->ob_type == _Slice_Type(); }
+bool _String_Check( PyObject *o ) { return o->ob_type == _String_Type(); }
+bool _TraceBack_Check( PyObject *v ) { return (v)->ob_type == _TraceBack_Type(); }
+bool _Tuple_Check( PyObject *op ) { return (op)->ob_type == _Tuple_Type(); }
+bool _Type_Check( PyObject *op ) { return (op)->ob_type == _Type_Type(); }
+
+#if PY_MAJOR_VERSION >= 2
+bool _Unicode_Check( PyObject *op ) { return (op)->ob_type == _Unicode_Type(); }
+#endif
+
+
+
+#if defined(PY_WIN32_DELAYLOAD_PYTHON_DLL)
+
+#if defined(MS_WINDOWS)
+#include <windows.h>
+
+
+static HMODULE python_dll;
+
+static PyObject *ptr__Exc_ArithmeticError = NULL;
+static PyObject *ptr__Exc_AssertionError = NULL;
+static PyObject *ptr__Exc_AttributeError = NULL;
+static PyObject *ptr__Exc_EnvironmentError = NULL;
+static PyObject *ptr__Exc_EOFError = NULL;
+static PyObject *ptr__Exc_Exception = NULL;
+static PyObject *ptr__Exc_FloatingPointError = NULL;
+static PyObject *ptr__Exc_ImportError = NULL;
+static PyObject *ptr__Exc_IndexError = NULL;
+static PyObject *ptr__Exc_IOError = NULL;
+static PyObject *ptr__Exc_KeyboardInterrupt = NULL;
+static PyObject *ptr__Exc_KeyError = NULL;
+static PyObject *ptr__Exc_LookupError = NULL;
+static PyObject *ptr__Exc_MemoryError = NULL;
+static PyObject *ptr__Exc_MemoryErrorInst = NULL;
+static PyObject *ptr__Exc_NameError = NULL;
+static PyObject *ptr__Exc_NotImplementedError = NULL;
+static PyObject *ptr__Exc_OSError = NULL;
+static PyObject *ptr__Exc_OverflowError = NULL;
+static PyObject *ptr__Exc_RuntimeError = NULL;
+static PyObject *ptr__Exc_StandardError = NULL;
+static PyObject *ptr__Exc_SyntaxError = NULL;
+static PyObject *ptr__Exc_SystemError = NULL;
+static PyObject *ptr__Exc_SystemExit = NULL;
+static PyObject *ptr__Exc_TypeError = NULL;
+static PyObject *ptr__Exc_ValueError = NULL;
+static PyObject *ptr__Exc_ZeroDivisionError = NULL;
+
+#ifdef MS_WINDOWS
+static PyObject *ptr__Exc_WindowsError = NULL;
+#endif
+
+#if PY_MAJOR_VERSION >= 2
+static PyObject *ptr__Exc_IndentationError = NULL;
+static PyObject *ptr__Exc_TabError = NULL;
+static PyObject *ptr__Exc_UnboundLocalError = NULL;
+static PyObject *ptr__Exc_UnicodeError = NULL;
+#endif
+
+static PyObject *ptr__PyNone = NULL;
+
+static PyTypeObject *ptr__Buffer_Type = NULL;
+static PyTypeObject *ptr__CFunction_Type = NULL;
+static PyTypeObject *ptr__Class_Type = NULL;
+static PyTypeObject *ptr__CObject_Type = NULL;
+static PyTypeObject *ptr__Complex_Type = NULL;
+static PyTypeObject *ptr__Dict_Type = NULL;
+static PyTypeObject *ptr__File_Type = NULL;
+static PyTypeObject *ptr__Float_Type = NULL;
+static PyTypeObject *ptr__Function_Type = NULL;
+static PyTypeObject *ptr__Instance_Type = NULL;
+static PyTypeObject *ptr__Int_Type = NULL;
+static PyTypeObject *ptr__List_Type = NULL;
+static PyTypeObject *ptr__Long_Type = NULL;
+static PyTypeObject *ptr__Method_Type = NULL;
+static PyTypeObject *ptr__Module_Type = NULL;
+static PyTypeObject *ptr__Range_Type = NULL;
+static PyTypeObject *ptr__Slice_Type = NULL;
+static PyTypeObject *ptr__String_Type = NULL;
+static PyTypeObject *ptr__TraceBack_Type = NULL;
+static PyTypeObject *ptr__Tuple_Type = NULL;
+static PyTypeObject *ptr__Type_Type = NULL;
+
+#if PY_MAJOR_VERSION >= 2
+static PyTypeObject *ptr__Unicode_Type = NULL;
+#endif
+
+static int *ptr_Py_DebugFlag = NULL;
+static int *ptr_Py_InteractiveFlag = NULL;
+static int *ptr_Py_OptimizeFlag = NULL;
+static int *ptr_Py_NoSiteFlag = NULL;
+static int *ptr_Py_TabcheckFlag = NULL;
+static int *ptr_Py_VerboseFlag = NULL;
+
+#if PY_MAJOR_VERSION >= 2
+static int *ptr_Py_UnicodeFlag = NULL;
+#endif
+
+static char **ptr__Py_PackageContext = NULL;
+
+#ifdef Py_REF_DEBUG
+int *ptr_Py_RefTotal;
+#endif
+
+
+//--------------------------------------------------------------------------------
+class GetAddressException
+ {
+public:
+ GetAddressException( const char *_name )
+ : name( _name )
+ {}
+ virtual ~GetAddressException() {}
+ const char *name;
+ };
+
+
+//--------------------------------------------------------------------------------
+static PyObject *GetPyObjectPointer_As_PyObjectPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return *(PyObject **)addr;
+ }
+
+static PyObject *GetPyObject_As_PyObjectPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return (PyObject *)addr;
+ }
+
+static PyTypeObject *GetPyTypeObjectPointer_As_PyTypeObjectPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return *(PyTypeObject **)addr;
+ }
+
+static PyTypeObject *GetPyTypeObject_As_PyTypeObjectPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return (PyTypeObject *)addr;
+ }
+
+static int *GetInt_as_IntPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return (int *)addr;
+ }
+
+static char **GetCharPointer_as_CharPointerPointer( const char *name )
+ {
+ FARPROC addr = GetProcAddress( python_dll, name );
+ if( addr == NULL )
+ throw GetAddressException( name );
+
+ return (char **)addr;
+ }
+
+
+#ifdef _DEBUG
+static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d_D.DLL";
+#else
+static const char python_dll_name_format[] = "PYTHON%1.1d%1.1d.DLL";
+#endif
+
+//--------------------------------------------------------------------------------
+bool InitialisePythonIndirectInterface()
+ {
+ char python_dll_name[sizeof(python_dll_name_format)];
+
+ sprintf( python_dll_name, python_dll_name_format, PY_MAJOR_VERSION, PY_MINOR_VERSION );
+
+ python_dll = LoadLibrary( python_dll_name );
+ if( python_dll == NULL )
+ return false;
+
+ try
+ {
+#ifdef Py_REF_DEBUG
+ ptr_Py_RefTotal = GetInt_as_IntPointer( "_Py_RefTotal" );
+#endif
+ ptr_Py_DebugFlag = GetInt_as_IntPointer( "Py_DebugFlag" );
+ ptr_Py_InteractiveFlag = GetInt_as_IntPointer( "Py_InteractiveFlag" );
+ ptr_Py_OptimizeFlag = GetInt_as_IntPointer( "Py_OptimizeFlag" );
+ ptr_Py_NoSiteFlag = GetInt_as_IntPointer( "Py_NoSiteFlag" );
+ ptr_Py_TabcheckFlag = GetInt_as_IntPointer( "Py_TabcheckFlag" );
+ ptr_Py_VerboseFlag = GetInt_as_IntPointer( "Py_VerboseFlag" );
+#if PY_MAJOR_VERSION >= 2
+ ptr_Py_UnicodeFlag = GetInt_as_IntPointer( "Py_UnicodeFlag" );
+#endif
+ ptr__Py_PackageContext = GetCharPointer_as_CharPointerPointer( "_Py_PackageContext" );
+
+ ptr__Exc_ArithmeticError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ArithmeticError" );
+ ptr__Exc_AssertionError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AssertionError" );
+ ptr__Exc_AttributeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_AttributeError" );
+ ptr__Exc_EnvironmentError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EnvironmentError" );
+ ptr__Exc_EOFError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_EOFError" );
+ ptr__Exc_Exception = GetPyObjectPointer_As_PyObjectPointer( "PyExc_Exception" );
+ ptr__Exc_FloatingPointError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_FloatingPointError" );
+ ptr__Exc_ImportError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ImportError" );
+ ptr__Exc_IndexError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndexError" );
+ ptr__Exc_IOError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IOError" );
+ ptr__Exc_KeyboardInterrupt = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyboardInterrupt" );
+ ptr__Exc_KeyError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_KeyError" );
+ ptr__Exc_LookupError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_LookupError" );
+ ptr__Exc_MemoryError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_MemoryError" );
+ ptr__Exc_MemoryErrorInst = GetPyObjectPointer_As_PyObjectPointer( "PyExc_MemoryErrorInst" );
+ ptr__Exc_NameError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_NameError" );
+ ptr__Exc_NotImplementedError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_NotImplementedError" );
+ ptr__Exc_OSError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OSError" );
+ ptr__Exc_OverflowError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_OverflowError" );
+ ptr__Exc_RuntimeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_RuntimeError" );
+ ptr__Exc_StandardError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_StandardError" );
+ ptr__Exc_SyntaxError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SyntaxError" );
+ ptr__Exc_SystemError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemError" );
+ ptr__Exc_SystemExit = GetPyObjectPointer_As_PyObjectPointer( "PyExc_SystemExit" );
+ ptr__Exc_TypeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TypeError" );
+ ptr__Exc_ValueError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ValueError" );
+#ifdef MS_WINDOWS
+ ptr__Exc_WindowsError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_WindowsError" );
+#endif
+ ptr__Exc_ZeroDivisionError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_ZeroDivisionError" );
+
+#if PY_MAJOR_VERSION >= 2
+ ptr__Exc_IndentationError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_IndentationError" );
+ ptr__Exc_TabError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_TabError" );
+ ptr__Exc_UnboundLocalError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnboundLocalError" );
+ ptr__Exc_UnicodeError = GetPyObjectPointer_As_PyObjectPointer( "PyExc_UnicodeError" );
+#endif
+ ptr__PyNone = GetPyObject_As_PyObjectPointer( "_Py_NoneStruct" );
+
+ ptr__Buffer_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyBuffer_Type" );
+ ptr__CFunction_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCFunction_Type" );
+ ptr__Class_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyClass_Type" );
+ ptr__CObject_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyCObject_Type" );
+ ptr__Complex_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyComplex_Type" );
+ ptr__Dict_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyDict_Type" );
+ ptr__File_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFile_Type" );
+ ptr__Float_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFloat_Type" );
+ ptr__Function_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyFunction_Type" );
+ ptr__Instance_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInstance_Type" );
+ ptr__Int_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyInt_Type" );
+ ptr__List_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyList_Type" );
+ ptr__Long_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyLong_Type" );
+ ptr__Method_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyMethod_Type" );
+ ptr__Module_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyModule_Type" );
+ ptr__Range_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyRange_Type" );
+ ptr__Slice_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PySlice_Type" );
+ ptr__String_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyString_Type" );
+ ptr__TraceBack_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTraceBack_Type" );
+ ptr__Tuple_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyTuple_Type" );
+ ptr__Type_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyType_Type" );
+
+#if PY_MAJOR_VERSION >= 2
+ ptr__Unicode_Type = GetPyTypeObject_As_PyTypeObjectPointer( "PyUnicode_Type" );
+#endif
+ }
+ catch( GetAddressException &e )
+ {
+ OutputDebugString( python_dll_name );
+ OutputDebugString( " does not contain symbol ");
+ OutputDebugString( e.name );
+ OutputDebugString( "\n" );
+
+ return false;
+ }
+
+ return true;
+ }
+
+//
+// Wrap variables as function calls
+//
+PyObject * _Exc_ArithmeticError() { return ptr__Exc_ArithmeticError; }
+PyObject * _Exc_AssertionError() { return ptr__Exc_AssertionError; }
+PyObject * _Exc_AttributeError() { return ptr__Exc_AttributeError; }
+PyObject * _Exc_EnvironmentError() { return ptr__Exc_EnvironmentError; }
+PyObject * _Exc_EOFError() { return ptr__Exc_EOFError; }
+PyObject * _Exc_Exception() { return ptr__Exc_Exception; }
+PyObject * _Exc_FloatingPointError() { return ptr__Exc_FloatingPointError; }
+PyObject * _Exc_ImportError() { return ptr__Exc_ImportError; }
+PyObject * _Exc_IndexError() { return ptr__Exc_IndexError; }
+PyObject * _Exc_IOError() { return ptr__Exc_IOError; }
+PyObject * _Exc_KeyboardInterrupt() { return ptr__Exc_KeyboardInterrupt; }
+PyObject * _Exc_KeyError() { return ptr__Exc_KeyError; }
+PyObject * _Exc_LookupError() { return ptr__Exc_LookupError; }
+PyObject * _Exc_MemoryError() { return ptr__Exc_MemoryError; }
+PyObject * _Exc_MemoryErrorInst() { return ptr__Exc_MemoryErrorInst; }
+PyObject * _Exc_NameError() { return ptr__Exc_NameError; }
+PyObject * _Exc_NotImplementedError() { return ptr__Exc_NotImplementedError; }
+PyObject * _Exc_OSError() { return ptr__Exc_OSError; }
+PyObject * _Exc_OverflowError() { return ptr__Exc_OverflowError; }
+PyObject * _Exc_RuntimeError() { return ptr__Exc_RuntimeError; }
+PyObject * _Exc_StandardError() { return ptr__Exc_StandardError; }
+PyObject * _Exc_SyntaxError() { return ptr__Exc_SyntaxError; }
+PyObject * _Exc_SystemError() { return ptr__Exc_SystemError; }
+PyObject * _Exc_SystemExit() { return ptr__Exc_SystemExit; }
+PyObject * _Exc_TypeError() { return ptr__Exc_TypeError; }
+PyObject * _Exc_ValueError() { return ptr__Exc_ValueError; }
+#ifdef MS_WINDOWS
+PyObject * _Exc_WindowsError() { return ptr__Exc_WindowsError; }
+#endif
+PyObject * _Exc_ZeroDivisionError() { return ptr__Exc_ZeroDivisionError; }
+
+#if PY_MAJOR_VERSION >= 2
+PyObject * _Exc_IndentationError() { return ptr__Exc_IndentationError; }
+PyObject * _Exc_TabError() { return ptr__Exc_TabError; }
+PyObject * _Exc_UnboundLocalError() { return ptr__Exc_UnboundLocalError; }
+PyObject * _Exc_UnicodeError() { return ptr__Exc_UnicodeError; }
+#endif
+
+//
+// wrap items in Object.h
+//
+PyObject * _None() { return ptr__PyNone; }
+
+
+PyTypeObject * _Buffer_Type() { return ptr__Buffer_Type; }
+PyTypeObject * _CFunction_Type() { return ptr__CFunction_Type; }
+PyTypeObject * _Class_Type() { return ptr__Class_Type; }
+PyTypeObject * _CObject_Type() { return ptr__CObject_Type; }
+PyTypeObject * _Complex_Type() { return ptr__Complex_Type; }
+PyTypeObject * _Dict_Type() { return ptr__Dict_Type; }
+PyTypeObject * _File_Type() { return ptr__File_Type; }
+PyTypeObject * _Float_Type() { return ptr__Float_Type; }
+PyTypeObject * _Function_Type() { return ptr__Function_Type; }
+PyTypeObject * _Instance_Type() { return ptr__Instance_Type; }
+PyTypeObject * _Int_Type() { return ptr__Int_Type; }
+PyTypeObject * _List_Type() { return ptr__List_Type; }
+PyTypeObject * _Long_Type() { return ptr__Long_Type; }
+PyTypeObject * _Method_Type() { return ptr__Method_Type; }
+PyTypeObject * _Module_Type() { return ptr__Module_Type; }
+PyTypeObject * _Range_Type() { return ptr__Range_Type; }
+PyTypeObject * _Slice_Type() { return ptr__Slice_Type; }
+PyTypeObject * _String_Type() { return ptr__String_Type; }
+PyTypeObject * _TraceBack_Type() { return ptr__TraceBack_Type; }
+PyTypeObject * _Tuple_Type() { return ptr__Tuple_Type; }
+PyTypeObject * _Type_Type() { return ptr__Type_Type; }
+
+#if PY_MAJOR_VERSION >= 2
+PyTypeObject * _Unicode_Type() { return ptr__Unicode_Type; }
+#endif
+
+char *__Py_PackageContext() { return *ptr__Py_PackageContext; }
+
+
+//
+// wrap the Python Flag variables
+//
+int &_Py_DebugFlag() { return *ptr_Py_DebugFlag; }
+int &_Py_InteractiveFlag() { return *ptr_Py_InteractiveFlag; }
+int &_Py_OptimizeFlag() { return *ptr_Py_OptimizeFlag; }
+int &_Py_NoSiteFlag() { return *ptr_Py_NoSiteFlag; }
+int &_Py_TabcheckFlag() { return *ptr_Py_TabcheckFlag; }
+int &_Py_VerboseFlag() { return *ptr_Py_VerboseFlag; }
+#if PY_MAJOR_VERSION >= 2
+int &_Py_UnicodeFlag() { return *ptr_Py_UnicodeFlag; }
+#endif
+
+void _XINCREF( PyObject *op )
+ {
+ // This function must match the contents of Py_XINCREF(op)
+ if( op == NULL )
+ return;
+
+#ifdef Py_REF_DEBUG
+ (*ptr_Py_RefTotal)++;
+#endif
+ (op)->ob_refcnt++;
+
+ }
+
+void _XDECREF( PyObject *op )
+ {
+ // This function must match the contents of Py_XDECREF(op);
+ if( op == NULL )
+ return;
+
+#ifdef Py_REF_DEBUG
+ (*ptr_Py_RefTotal)--;
+#endif
+
+ if (--(op)->ob_refcnt == 0)
+ _Py_Dealloc((PyObject *)(op));
+ }
+
+
+#else
+#error "Can only delay load under Win32"
+#endif
+
+#else
+
+//
+// Duplicated these declarations from rangeobject.h which is missing the
+// extern "C". This has been reported as a bug upto and include 2.1
+//
+extern "C" DL_IMPORT(PyTypeObject) PyRange_Type;
+extern "C" DL_IMPORT(PyObject *) PyRange_New(long, long, long, int);
+
+
+//================================================================================
+//
+// Map onto Macros
+//
+//================================================================================
+
+//
+// Wrap variables as function calls
+//
+
+PyObject * _Exc_ArithmeticError() { return ::PyExc_ArithmeticError; }
+PyObject * _Exc_AssertionError() { return ::PyExc_AssertionError; }
+PyObject * _Exc_AttributeError() { return ::PyExc_AttributeError; }
+PyObject * _Exc_EnvironmentError() { return ::PyExc_EnvironmentError; }
+PyObject * _Exc_EOFError() { return ::PyExc_EOFError; }
+PyObject * _Exc_Exception() { return ::PyExc_Exception; }
+PyObject * _Exc_FloatingPointError() { return ::PyExc_FloatingPointError; }
+PyObject * _Exc_ImportError() { return ::PyExc_ImportError; }
+PyObject * _Exc_IndexError() { return ::PyExc_IndexError; }
+PyObject * _Exc_IOError() { return ::PyExc_IOError; }
+PyObject * _Exc_KeyboardInterrupt() { return ::PyExc_KeyboardInterrupt; }
+PyObject * _Exc_KeyError() { return ::PyExc_KeyError; }
+PyObject * _Exc_LookupError() { return ::PyExc_LookupError; }
+PyObject * _Exc_MemoryError() { return ::PyExc_MemoryError; }
+PyObject * _Exc_MemoryErrorInst() { return ::PyExc_MemoryErrorInst; }
+PyObject * _Exc_NameError() { return ::PyExc_NameError; }
+PyObject * _Exc_NotImplementedError() { return ::PyExc_NotImplementedError; }
+PyObject * _Exc_OSError() { return ::PyExc_OSError; }
+PyObject * _Exc_OverflowError() { return ::PyExc_OverflowError; }
+PyObject * _Exc_RuntimeError() { return ::PyExc_RuntimeError; }
+PyObject * _Exc_StandardError() { return ::PyExc_StandardError; }
+PyObject * _Exc_SyntaxError() { return ::PyExc_SyntaxError; }
+PyObject * _Exc_SystemError() { return ::PyExc_SystemError; }
+PyObject * _Exc_SystemExit() { return ::PyExc_SystemExit; }
+PyObject * _Exc_TypeError() { return ::PyExc_TypeError; }
+PyObject * _Exc_ValueError() { return ::PyExc_ValueError; }
+PyObject * _Exc_ZeroDivisionError() { return ::PyExc_ZeroDivisionError; }
+
+#ifdef MS_WINDOWS
+PyObject * _Exc_WindowsError() { return ::PyExc_WindowsError; }
+#endif
+
+
+#if PY_MAJOR_VERSION >= 2
+PyObject * _Exc_IndentationError() { return ::PyExc_IndentationError; }
+PyObject * _Exc_TabError() { return ::PyExc_TabError; }
+PyObject * _Exc_UnboundLocalError() { return ::PyExc_UnboundLocalError; }
+PyObject * _Exc_UnicodeError() { return ::PyExc_UnicodeError; }
+#endif
+
+
+//
+// wrap items in Object.h
+//
+PyObject * _None() { return &::_Py_NoneStruct; }
+
+PyTypeObject * _Buffer_Type() { return &PyBuffer_Type; }
+PyTypeObject * _CFunction_Type() { return &PyCFunction_Type; }
+PyTypeObject * _Class_Type() { return &PyClass_Type; }
+PyTypeObject * _CObject_Type() { return &PyCObject_Type; }
+PyTypeObject * _Complex_Type() { return &PyComplex_Type; }
+PyTypeObject * _Dict_Type() { return &PyDict_Type; }
+PyTypeObject * _File_Type() { return &PyFile_Type; }
+PyTypeObject * _Float_Type() { return &PyFloat_Type; }
+PyTypeObject * _Function_Type() { return &PyFunction_Type; }
+PyTypeObject * _Instance_Type() { return &PyInstance_Type; }
+PyTypeObject * _Int_Type() { return &PyInt_Type; }
+PyTypeObject * _List_Type() { return &PyList_Type; }
+PyTypeObject * _Long_Type() { return &PyLong_Type; }
+PyTypeObject * _Method_Type() { return &PyMethod_Type; }
+PyTypeObject * _Module_Type() { return &PyModule_Type; }
+PyTypeObject * _Range_Type() { return &PyRange_Type; }
+PyTypeObject * _Slice_Type() { return &PySlice_Type; }
+PyTypeObject * _String_Type() { return &PyString_Type; }
+PyTypeObject * _TraceBack_Type() { return &PyTraceBack_Type; }
+PyTypeObject * _Tuple_Type() { return &PyTuple_Type; }
+PyTypeObject * _Type_Type() { return &PyType_Type; }
+
+#if PY_MAJOR_VERSION >= 2
+PyTypeObject * _Unicode_Type() { return &PyUnicode_Type; }
+#endif
+
+//
+// wrap flags
+//
+int &_Py_DebugFlag() { return Py_DebugFlag; }
+int &_Py_InteractiveFlag() { return Py_InteractiveFlag; }
+int &_Py_OptimizeFlag() { return Py_OptimizeFlag; }
+int &_Py_NoSiteFlag() { return Py_NoSiteFlag; }
+int &_Py_TabcheckFlag() { return Py_TabcheckFlag; }
+int &_Py_VerboseFlag() { return Py_VerboseFlag; }
+#if PY_MAJOR_VERSION >= 2
+int &_Py_UnicodeFlag() { return Py_UnicodeFlag; }
+#endif
+char *__Py_PackageContext() { return _Py_PackageContext; }
+
+//
+// Needed to keep the abstactions for delayload interface
+//
+void _XINCREF( PyObject *op )
+ {
+ Py_XINCREF(op);
+ }
+
+void _XDECREF( PyObject *op )
+ {
+ Py_XDECREF(op);
+ }
+
+#endif
+}
diff --git a/lib/kross/python/cxx/IndirectPythonInterface.hxx b/lib/kross/python/cxx/IndirectPythonInterface.hxx
new file mode 100644
index 00000000..8f2d275d
--- /dev/null
+++ b/lib/kross/python/cxx/IndirectPythonInterface.hxx
@@ -0,0 +1,156 @@
+#ifndef __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
+#define __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
+
+#include <Python.h>
+
+namespace Py
+{
+bool InitialisePythonIndirectInterface();
+
+//
+// Wrap Exception variables as function calls
+//
+PyObject * _Exc_Exception();
+PyObject * _Exc_StandardError();
+PyObject * _Exc_ArithmeticError();
+PyObject * _Exc_LookupError();
+
+PyObject * _Exc_AssertionError();
+PyObject * _Exc_AttributeError();
+PyObject * _Exc_EOFError();
+PyObject * _Exc_FloatingPointError();
+PyObject * _Exc_EnvironmentError();
+PyObject * _Exc_IOError();
+PyObject * _Exc_OSError();
+PyObject * _Exc_ImportError();
+PyObject * _Exc_IndexError();
+PyObject * _Exc_KeyError();
+PyObject * _Exc_KeyboardInterrupt();
+PyObject * _Exc_MemoryError();
+PyObject * _Exc_NameError();
+PyObject * _Exc_OverflowError();
+PyObject * _Exc_RuntimeError();
+PyObject * _Exc_NotImplementedError();
+PyObject * _Exc_SyntaxError();
+PyObject * _Exc_SystemError();
+PyObject * _Exc_SystemExit();
+PyObject * _Exc_TypeError();
+PyObject * _Exc_ValueError();
+PyObject * _Exc_ZeroDivisionError();
+#ifdef MS_WINDOWS
+PyObject * _Exc_WindowsError();
+#endif
+
+PyObject * _Exc_MemoryErrorInst();
+
+#if PY_MAJOR_VERSION >= 2
+PyObject * _Exc_IndentationError();
+PyObject * _Exc_TabError();
+PyObject * _Exc_UnboundLocalError();
+PyObject * _Exc_UnicodeError();
+#endif
+
+//
+// Wrap Object variables as function calls
+//
+PyObject * _None();
+
+
+//
+// Wrap Type variables as function calls
+//
+PyTypeObject * _List_Type();
+bool _List_Check( PyObject *o );
+
+PyTypeObject * _Buffer_Type();
+bool _Buffer_Check( PyObject *op );
+
+PyTypeObject * _Class_Type();
+bool _Class_Check( PyObject *op );
+
+PyTypeObject * _Instance_Type();
+bool _Instance_Check( PyObject *op );
+
+PyTypeObject * _Method_Type();
+bool _Method_Check( PyObject *op );
+
+PyTypeObject * _CObject_Type();
+bool _CObject_Check( PyObject *op );
+
+PyTypeObject * _Complex_Type();
+bool _Complex_Check( PyObject *op );
+
+PyTypeObject * _Dict_Type();
+bool _Dict_Check( PyObject *op );
+
+PyTypeObject * _File_Type();
+bool _File_Check( PyObject *op );
+
+PyTypeObject * _Float_Type();
+bool _Float_Check( PyObject *op );
+
+PyTypeObject * _Frame_Type();
+bool _Frame_Check( PyObject *op );
+
+PyTypeObject * _Function_Type();
+bool _Function_Check( PyObject *op );
+
+PyTypeObject * _Int_Type();
+bool _Int_Check( PyObject *op );
+
+PyTypeObject * _List_Type();
+bool _List_Check( PyObject *op );
+
+PyTypeObject * _Long_Type();
+bool _Long_Check( PyObject *op );
+
+PyTypeObject * _CFunction_Type();
+bool _CFunction_Check( PyObject *op );
+
+PyTypeObject * _Module_Type();
+bool _Module_Check( PyObject *op );
+
+PyTypeObject * _Type_Type();
+bool _Type_Check( PyObject *op );
+
+PyTypeObject * _Range_Type();
+bool _Range_Check( PyObject *op );
+
+PyTypeObject * _Slice_Type();
+bool _Slice_Check( PyObject *op );
+
+PyTypeObject * _String_Type();
+bool _String_Check( PyObject *op );
+
+PyTypeObject * _Unicode_Type();
+bool _Unicode_Check( PyObject *op );
+
+PyTypeObject * _TraceBack_Type();
+bool _TraceBack_Check( PyObject *v );
+
+PyTypeObject * _Tuple_Type();
+bool _Tuple_Check( PyObject *op );
+
+#if PY_MAJOR_VERSION >= 2
+PyTypeObject * _Unicode_Type();
+bool _Unicode_Check( PyObject *op );
+#endif
+
+int &_Py_DebugFlag();
+int &_Py_InteractiveFlag();
+int &_Py_OptimizeFlag();
+int &_Py_NoSiteFlag();
+int &_Py_TabcheckFlag();
+int &_Py_VerboseFlag();
+
+#if PY_MAJOR_VERSION >= 2
+int &_Py_UnicodeFlag();
+#endif
+
+void _XINCREF( PyObject *op );
+void _XDECREF( PyObject *op );
+
+char *__Py_PackageContext();
+}
+
+#endif // __CXX_INDIRECT_PYTHON_INTERFACE__HXX__
diff --git a/lib/kross/python/cxx/Legal.html b/lib/kross/python/cxx/Legal.html
new file mode 100755
index 00000000..cf6a530f
--- /dev/null
+++ b/lib/kross/python/cxx/Legal.html
@@ -0,0 +1,40 @@
+<html>
+
+<head>
+<title>Legal Notice</title>
+<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
+</head>
+
+<body>
+
+<h1>Legal Notice</h1>
+
+<p>*** Legal Notice for all LLNL-contributed files *** </p>
+
+<p>Copyright (c) 1996. The Regents of the University of California. All rights reserved. </p>
+
+<p>Permission to use, copy, modify, and distribute this software for any purpose without
+fee is hereby granted, provided that this entire notice is included in all copies of any
+software which is or includes a copy or modification of this software and in all copies of
+the supporting documentation for such software. </p>
+
+<p>This work was produced at the University of California, Lawrence Livermore National
+Laboratory under contract no. W-7405-ENG-48 between the U.S. Department of Energy and The
+Regents of the University of California for the operation of UC LLNL. </p>
+
+<h2>DISCLAIMER </h2>
+
+<p>This software was prepared as an account of work sponsored by an agency of the United
+States Government. Neither the United States Government nor the University of California
+nor any of their employees, makes any warranty, express or implied, or assumes any
+liability or responsibility for the accuracy, completeness, or usefulness of any
+information, apparatus, product, or process disclosed, or represents that its use would
+not infringe privately-owned rights. Reference herein to any specific commercial products,
+process, or service by trade name, trademark, manufacturer, or otherwise, does not
+necessarily constitute or imply its endorsement, recommendation, or favoring by the United
+States Government or the University of California. The views and opinions of authors
+expressed herein do not necessarily state or reflect those of the United States Government
+or the University of California, and shall not be used for advertising or product
+endorsement purposes.</p>
+</body>
+</html>
diff --git a/lib/kross/python/cxx/Makefile.am b/lib/kross/python/cxx/Makefile.am
new file mode 100644
index 00000000..d1c72c87
--- /dev/null
+++ b/lib/kross/python/cxx/Makefile.am
@@ -0,0 +1,19 @@
+include $(top_srcdir)/lib/kross/Makefile.global
+
+noinst_LTLIBRARIES = libkrosspythoncxx.la
+
+libkrosspythoncxx_la_SOURCES = \
+ cxxsupport.cxx \
+ cxx_extensions.cxx \
+ cxxextensions.c \
+ IndirectPythonInterface.cxx
+
+libkrosspythoncxx_la_LDFLAGS = $(LIBPYTHON) $(all_libraries) -Wnounresolved
+
+METASOURCES = AUTO
+INCLUDES = $(KROSS_INCLUDES) $(PYTHONINC) $(all_includes)
+SUBDIRS = .
+
+clean:
+ @rm -f *.o 2> /dev/null
+ @rm -f $(BIN) 2> /dev/null
diff --git a/lib/kross/python/cxx/Objects.hxx b/lib/kross/python/cxx/Objects.hxx
new file mode 100644
index 00000000..41648320
--- /dev/null
+++ b/lib/kross/python/cxx/Objects.hxx
@@ -0,0 +1,2804 @@
+//----------------------------------*-C++-*----------------------------------//
+// Copyright 1998 The Regents of the University of California.
+// All rights reserved. See LEGAL.LLNL for full text and disclaimer.
+//---------------------------------------------------------------------------//
+
+#ifndef __CXX_Objects__h
+#define __CXX_Objects__h
+
+// Prevent warnings
+#if defined(_XOPEN_SOURCE)
+#undef _XOPEN_SOURCE
+#endif
+
+#include "Python.h"
+#include "Config.hxx"
+#include "Exception.hxx"
+
+
+#include <iostream>
+#include STR_STREAM
+#include <string>
+#include <iterator>
+#include <utility>
+#include <typeinfo>
+
+namespace Py
+ {
+ typedef int sequence_index_type; // type of an index into a sequence
+
+ // Forward declarations
+ class Object;
+ class Type;
+ template<TEMPLATE_TYPENAME T> class SeqBase;
+ class String;
+ class List;
+ template<TEMPLATE_TYPENAME T> class MapBase;
+
+ // new_reference_to also overloaded below on Object
+ inline PyObject* new_reference_to(PyObject* p)
+ {
+ Py::_XINCREF(p);
+ return p;
+ }
+
+ // returning Null() from an extension method triggers a
+ // Python exception
+ inline PyObject* Null()
+ {
+ return (static_cast<PyObject*>(0));
+ }
+
+ //===========================================================================//
+ // class Object
+ // The purpose of this class is to serve as the most general kind of
+ // Python object, for the purpose of writing C++ extensions in Python
+ // Objects hold a PyObject* which they own. This pointer is always a
+ // valid pointer to a Python object. In children we must maintain this behavior.
+ //
+ // Instructions on how to make your own class MyType descended from Object:
+ // (0) Pick a base class, either Object or perhaps SeqBase<T> or MapBase<T>.
+ // This example assumes Object.
+
+ // (1) Write a routine int MyType_Check (PyObject *) modeled after PyInt_Check,
+ // PyFloat_Check, etc.
+
+ // (2) Add method accepts:
+ // virtual bool accepts (PyObject *pyob) const {
+ // return pyob && MyType_Check (pyob);
+ // }
+
+ // (3) Include the following constructor and copy constructor
+ //
+ /*
+ explicit MyType (PyObject *pyob): Object(pyob) {
+ validate();
+ }
+
+ MyType(const Object& other): Object(other.ptr()) {
+ validate();
+ }
+ */
+
+ // Alernate version for the constructor to allow for construction from owned pointers:
+ /*
+ explicit MyType (PyObject *pyob): Object(pyob) {
+ validate();
+ }
+ */
+
+ // You may wish to add other constructors; see the classes below for examples.
+ // Each constructor must use "set" to set the pointer
+ // and end by validating the pointer you have created.
+
+ // (4) Each class needs at least these two assignment operators:
+ /*
+ MyType& operator= (const Object& rhs) {
+ return (*this = *rhs);
+ }
+
+ Mytype& operator= (PyObject* rhsp) {
+ if(ptr() == rhsp) return *this;
+ set(rhsp);
+ return *this;
+ }
+ */
+ // Note on accepts: constructors call the base class
+ // version of a virtual when calling the base class constructor,
+ // so the test has to be done explicitly in a descendent.
+
+ // If you are inheriting from PythonExtension<T> to define an object
+ // note that it contains PythonExtension<T>::check
+ // which you can use in accepts when writing a wrapper class.
+ // See Demo/range.h and Demo/range.cxx for an example.
+
+ class Object
+ {
+ private:
+ // the pointer to the Python object
+ // Only Object sets this directly.
+ // The default constructor for Object sets it to Py_None and
+ // child classes must use "set" to set it
+ //
+ PyObject* p;
+
+ protected:
+
+ void set (PyObject* pyob, bool owned = false)
+ {
+ release();
+ p = pyob;
+ if (!owned)
+ {
+ Py::_XINCREF (p);
+ }
+ validate();
+ }
+
+ void release ()
+ {
+ Py::_XDECREF (p);
+ p = 0;
+ }
+
+ void validate()
+ {
+ // release pointer if not the right type
+ if (! accepts (p))
+ {
+ release ();
+ if(PyErr_Occurred())
+ { // Error message already set
+ throw Exception();
+ }
+ // Better error message if RTTI available
+#if defined( _CPPRTTI )
+ std::string s("Error creating object of type ");
+ s += (typeid (*this)).name();
+ throw TypeError (s);
+#else
+ throw TypeError ("CXX: type error.");
+#endif
+ }
+ }
+
+ public:
+ // Constructor acquires new ownership of pointer unless explicitly told not to.
+ explicit Object (PyObject* pyob=Py::_None(), bool owned = false): p (pyob)
+ {
+ if(!owned)
+ {
+ Py::_XINCREF (p);
+ }
+ validate();
+ }
+
+ // Copy constructor acquires new ownership of pointer
+ Object (const Object& ob): p(ob.p)
+ {
+ Py::_XINCREF (p);
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+ Object& operator= (const Object& rhs)
+ {
+ set(rhs.p);
+ return *this;
+ }
+
+ Object& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+
+ // Destructor
+ virtual ~Object ()
+ {
+ release ();
+ }
+
+ // Loaning the pointer to others, retain ownership
+ PyObject* operator* () const
+ {
+ return p;
+ }
+
+ // Explicit reference_counting changes
+ void increment_reference_count()
+ {
+ Py::_XINCREF(p);
+ }
+
+ void decrement_reference_count()
+ {
+ // not allowed to commit suicide, however
+ if(reference_count() == 1)
+ throw RuntimeError("Object::decrement_reference_count error.");
+ Py::_XDECREF(p);
+ }
+ // Would like to call this pointer() but messes up STL in SeqBase<T>
+ PyObject* ptr () const
+ {
+ return p;
+ }
+
+ //
+ // Queries
+ //
+
+ // Can pyob be used in this object's constructor?
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return (pyob != 0);
+ }
+
+ int reference_count () const
+ { // the reference count
+ return p ? p->ob_refcnt : 0;
+ }
+
+ Type type () const; // the type object associated with this one
+
+ String str () const; // the str() representation
+
+ std::string as_string() const;
+
+ String repr () const; // the repr () representation
+
+ List dir () const; // the dir() list
+
+ bool hasAttr (const std::string& s) const
+ {
+ return PyObject_HasAttrString (p, const_cast<char*>(s.c_str())) ? true: false;
+ }
+
+ Object getAttr (const std::string& s) const
+ {
+ return Object (PyObject_GetAttrString (p, const_cast<char*>(s.c_str())), true);
+ }
+
+ Object getItem (const Object& key) const
+ {
+ return Object (PyObject_GetItem(p, *key), true);
+ }
+
+ long hashValue () const
+ {
+ return PyObject_Hash (p);
+ }
+
+ //
+ // int print (FILE* fp, int flags=Py_Print_RAW)
+ // {
+ // return PyObject_Print (p, fp, flags);
+ // }
+ //
+ bool is(PyObject *pother) const
+ { // identity test
+ return p == pother;
+ }
+
+ bool is(const Object& other) const
+ { // identity test
+ return p == other.p;
+ }
+
+ bool isCallable () const
+ {
+ return PyCallable_Check (p) != 0;
+ }
+
+ bool isInstance () const
+ {
+ return PyInstance_Check (p) != 0;
+ }
+
+ bool isDict () const
+ {
+ return Py::_Dict_Check (p);
+ }
+
+ bool isList () const
+ {
+ return Py::_List_Check (p);
+ }
+
+ bool isMapping () const
+ {
+ return PyMapping_Check (p) != 0;
+ }
+
+ bool isNumeric () const
+ {
+ return PyNumber_Check (p) != 0;
+ }
+
+ bool isSequence () const
+ {
+ return PySequence_Check (p) != 0;
+ }
+
+ bool isTrue () const
+ {
+ return PyObject_IsTrue (p) != 0;
+ }
+
+ bool isType (const Type& t) const;
+
+ bool isTuple() const
+ {
+ return Py::_Tuple_Check(p);
+ }
+
+ bool isString() const
+ {
+ return Py::_String_Check(p) || Py::_Unicode_Check(p);
+ }
+
+ bool isUnicode() const
+ {
+ return Py::_Unicode_Check(p);
+ }
+
+ // Commands
+ void setAttr (const std::string& s, const Object& value)
+ {
+ if(PyObject_SetAttrString (p, const_cast<char*>(s.c_str()), *value) == -1)
+ throw AttributeError ("getAttr failed.");
+ }
+
+ void delAttr (const std::string& s)
+ {
+ if(PyObject_DelAttrString (p, const_cast<char*>(s.c_str())) == -1)
+ throw AttributeError ("delAttr failed.");
+ }
+
+ // PyObject_SetItem is too weird to be using from C++
+ // so it is intentionally omitted.
+
+ void delItem (const Object& /*key*/)
+ {
+ //if(PyObject_DelItem(p, *key) == -1)
+ // failed to link on Windows?
+ throw KeyError("delItem failed.");
+ }
+ // Equality and comparison use PyObject_Compare
+
+ bool operator==(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k == 0;
+ }
+
+ bool operator!=(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k != 0;
+
+ }
+
+ bool operator>=(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k >= 0;
+ }
+
+ bool operator<=(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k <= 0;
+ }
+
+ bool operator<(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k < 0;
+ }
+
+ bool operator>(const Object& o2) const
+ {
+ int k = PyObject_Compare (p, *o2);
+ if (PyErr_Occurred()) throw Exception();
+ return k > 0;
+ }
+ };
+ // End of class Object
+ inline PyObject* new_reference_to(const Object& g)
+ {
+ PyObject* p = g.ptr();
+ Py::_XINCREF(p);
+ return p;
+ }
+
+ // Nothing() is what an extension method returns if
+ // there is no other return value.
+ inline Object Nothing()
+ {
+ return Object(Py::_None());
+ }
+
+ // Python special None value
+ inline Object None()
+ {
+ return Object(Py::_None());
+ }
+
+ // TMM: 31May'01 - Added the #ifndef so I can exlude iostreams.
+#ifndef CXX_NO_IOSTREAMS
+ std::ostream& operator<< (std::ostream& os, const Object& ob);
+#endif
+
+ // Class Type
+ class Type: public Object
+ {
+ public:
+ explicit Type (PyObject* pyob, bool owned = false): Object(pyob, owned)
+ {
+ validate();
+ }
+
+ Type (const Object& ob): Object(*ob)
+ {
+ validate();
+ }
+
+ Type(const Type& t): Object(t)
+ {
+ validate();
+ }
+
+ Type& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Type& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Type_Check (pyob);
+ }
+ };
+
+
+ //
+ // Convert an owned Python pointer into a CXX Object
+ //
+ inline Object asObject (PyObject *p)
+ {
+ return Object(p, true);
+ }
+
+
+
+
+ // ===============================================
+ // class Int
+ class Int: public Object
+ {
+ public:
+ // Constructor
+ explicit Int (PyObject *pyob, bool owned = false): Object (pyob, owned)
+ {
+ validate();
+ }
+
+ Int (const Int& ob): Object(*ob)
+ {
+ validate();
+ }
+
+ // create from long
+ explicit Int (long v = 0L): Object(PyInt_FromLong(v), true)
+ {
+ validate();
+ }
+
+ // create from int
+ explicit Int (int v)
+ {
+ long w = v;
+ set(PyInt_FromLong(w), true);
+ validate();
+ }
+
+ Int (const Object& ob)
+ {
+ set(PyNumber_Int(*ob), true);
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+
+ Int& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Int& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (PyNumber_Int(rhsp), true);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Int_Check (pyob);
+ }
+ // convert to long
+ operator long() const
+ {
+ return PyInt_AsLong (ptr());
+ }
+ // assign from an int
+ Int& operator= (int v)
+ {
+ set (PyInt_FromLong (long(v)), true);
+ return *this;
+ }
+ // assign from long
+ Int& operator= (long v)
+ {
+ set (PyInt_FromLong (v), true);
+ return *this;
+ }
+ };
+
+ // ===============================================
+ // class Long
+ class Long: public Object
+ {
+ public:
+ // Constructor
+ explicit Long (PyObject *pyob, bool owned = false): Object (pyob, owned)
+ {
+ validate();
+ }
+
+ Long (const Long& ob): Object(ob.ptr())
+ {
+ validate();
+ }
+
+ // create from long
+ explicit Long (long v = 0L)
+ : Object(PyLong_FromLong(v), true)
+ {
+ validate();
+ }
+ // create from int
+ explicit Long (int v)
+ : Object(PyLong_FromLong(static_cast<long>(v)), true)
+ {
+ validate();
+ }
+
+ // create from unsigned long
+ explicit Long (unsigned long v)
+ : Object(PyLong_FromUnsignedLong(v), true)
+ {
+ validate();
+ }
+
+ // try to create from any object
+ Long (const Object& ob)
+ : Object(PyNumber_Long(*ob), true)
+ {
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+
+ Long& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Long& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (PyNumber_Long(rhsp), true);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Long_Check (pyob);
+ }
+ // convert to long
+ operator long() const
+ {
+ return PyLong_AsLong (ptr());
+ }
+ operator double() const
+ {
+ return PyLong_AsDouble (ptr());
+ }
+ operator unsigned long() const
+ {
+ return PyLong_AsUnsignedLong (ptr());
+ }
+ // assign from an int
+ Long& operator= (int v)
+ {
+ set(PyLong_FromLong (long(v)), true);
+ return *this;
+ }
+ // assign from long
+ Long& operator= (long v)
+ {
+ set(PyLong_FromLong (v), true);
+ return *this;
+ }
+ // assign from unsigned long
+ Long& operator= (unsigned long v)
+ {
+ set(PyLong_FromUnsignedLong (v), true);
+ return *this;
+ }
+ };
+
+ // ===============================================
+ // class Float
+ //
+ class Float: public Object
+ {
+ public:
+ // Constructor
+ explicit Float (PyObject *pyob, bool owned = false): Object(pyob, owned)
+ {
+ validate();
+ }
+
+ Float (const Float& f): Object(f)
+ {
+ validate();
+ }
+
+ // make from double
+ explicit Float (double v=0.0)
+ : Object(PyFloat_FromDouble (v), true)
+ {
+ validate();
+ }
+
+ // try to make from any object
+ Float (const Object& ob)
+ : Object(PyNumber_Float(*ob), true)
+ {
+ validate();
+ }
+
+ Float& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Float& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (PyNumber_Float(rhsp), true);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Float_Check (pyob);
+ }
+ // convert to double
+ operator double () const
+ {
+ return PyFloat_AsDouble (ptr());
+ }
+ // assign from a double
+ Float& operator= (double v)
+ {
+ set(PyFloat_FromDouble (v), true);
+ return *this;
+ }
+ // assign from an int
+ Float& operator= (int v)
+ {
+ set(PyFloat_FromDouble (double(v)), true);
+ return *this;
+ }
+ // assign from long
+ Float& operator= (long v)
+ {
+ set(PyFloat_FromDouble (double(v)), true);
+ return *this;
+ }
+ // assign from an Int
+ Float& operator= (const Int& iob)
+ {
+ set(PyFloat_FromDouble (double(long(iob))), true);
+ return *this;
+ }
+ };
+
+ // ===============================================
+ // class Complex
+ class Complex: public Object
+ {
+ public:
+ // Constructor
+ explicit Complex (PyObject *pyob, bool owned = false): Object(pyob, owned)
+ {
+ validate();
+ }
+
+ Complex (const Complex& f): Object(f)
+ {
+ validate();
+ }
+
+ // make from double
+ explicit Complex (double v=0.0, double w=0.0)
+ :Object(PyComplex_FromDoubles (v, w), true)
+ {
+ validate();
+ }
+
+ Complex& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Complex& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Complex_Check (pyob);
+ }
+ // convert to Py_complex
+ operator Py_complex () const
+ {
+ return PyComplex_AsCComplex (ptr());
+ }
+ // assign from a Py_complex
+ Complex& operator= (const Py_complex& v)
+ {
+ set(PyComplex_FromCComplex (v), true);
+ return *this;
+ }
+ // assign from a double
+ Complex& operator= (double v)
+ {
+ set(PyComplex_FromDoubles (v, 0.0), true);
+ return *this;
+ }
+ // assign from an int
+ Complex& operator= (int v)
+ {
+ set(PyComplex_FromDoubles (double(v), 0.0), true);
+ return *this;
+ }
+ // assign from long
+ Complex& operator= (long v)
+ {
+ set(PyComplex_FromDoubles (double(v), 0.0), true);
+ return *this;
+ }
+ // assign from an Int
+ Complex& operator= (const Int& iob)
+ {
+ set(PyComplex_FromDoubles (double(long(iob)), 0.0), true);
+ return *this;
+ }
+
+ double real() const
+ {
+ return PyComplex_RealAsDouble(ptr());
+ }
+
+ double imag() const
+ {
+ return PyComplex_ImagAsDouble(ptr());
+ }
+ };
+ // Sequences
+ // Sequences are here represented as sequences of items of type T.
+ // The base class SeqBase<T> represents that.
+ // In basic Python T is always "Object".
+
+ // seqref<T> is what you get if you get elements from a non-const SeqBase<T>.
+ // Note: seqref<T> could probably be a nested class in SeqBase<T> but that might stress
+ // some compilers needlessly. Simlarly for mapref later.
+
+ // While this class is not intended for enduser use, it needs some public
+ // constructors for the benefit of the STL.
+
+ // See Scott Meyer's More Essential C++ for a description of proxies.
+ // This application is even more complicated. We are doing an unusual thing
+ // in having a double proxy. If we want the STL to work
+ // properly we have to compromise by storing the rvalue inside. The
+ // entire Object API is repeated so that things like s[i].isList() will
+ // work properly.
+
+ // Still, once in a while a weird compiler message may occur using expressions like x[i]
+ // Changing them to Object(x[i]) helps the compiler to understand that the
+ // conversion of a seqref to an Object is wanted.
+
+ template<TEMPLATE_TYPENAME T>
+ class seqref
+ {
+ protected:
+ SeqBase<T>& s; // the sequence
+ int offset; // item number
+ T the_item; // lvalue
+ public:
+
+ seqref (SeqBase<T>& seq, sequence_index_type j)
+ : s(seq), offset(j), the_item (s.getItem(j))
+ {}
+
+ seqref (const seqref<T>& range)
+ : s(range.s), offset(range.offset), the_item(range.the_item)
+ {}
+
+ // TMM: added this seqref ctor for use with STL algorithms
+ seqref (Object& obj)
+ : s(dynamic_cast< SeqBase<T>&>(obj))
+ , offset( NULL )
+ , the_item(s.getItem(offset))
+ {}
+ ~seqref()
+ {}
+
+ operator T() const
+ { // rvalue
+ return the_item;
+ }
+
+ seqref<T>& operator=(const seqref<T>& rhs)
+ { //used as lvalue
+ the_item = rhs.the_item;
+ s.setItem(offset, the_item);
+ return *this;
+ }
+
+ seqref<T>& operator=(const T& ob)
+ { // used as lvalue
+ the_item = ob;
+ s.setItem(offset, ob);
+ return *this;
+ }
+
+ // forward everything else to the item
+ PyObject* ptr () const
+ {
+ return the_item.ptr();
+ }
+
+ int reference_count () const
+ { // the reference count
+ return the_item.reference_count();
+ }
+
+ Type type () const
+ {
+ return the_item.type();
+ }
+
+ String str () const;
+
+ String repr () const;
+
+ bool hasAttr (const std::string& attr_name) const
+ {
+ return the_item.hasAttr(attr_name);
+ }
+
+ Object getAttr (const std::string& attr_name) const
+ {
+ return the_item.getAttr(attr_name);
+ }
+
+ Object getItem (const Object& key) const
+ {
+ return the_item.getItem(key);
+ }
+
+ long hashValue () const
+ {
+ return the_item.hashValue();
+ }
+
+ bool isCallable () const
+ {
+ return the_item.isCallable();
+ }
+
+ bool isInstance () const
+ {
+ return the_item.isInstance();
+ }
+
+ bool isDict () const
+ {
+ return the_item.isDict();
+ }
+
+ bool isList () const
+ {
+ return the_item.isList();
+ }
+
+ bool isMapping () const
+ {
+ return the_item.isMapping();
+ }
+
+ bool isNumeric () const
+ {
+ return the_item.isNumeric();
+ }
+
+ bool isSequence () const
+ {
+ return the_item.isSequence();
+ }
+
+ bool isTrue () const
+ {
+ return the_item.isTrue();
+ }
+
+ bool isType (const Type& t) const
+ {
+ return the_item.isType (t);
+ }
+
+ bool isTuple() const
+ {
+ return the_item.isTuple();
+ }
+
+ bool isString() const
+ {
+ return the_item.isString();
+ }
+ // Commands
+ void setAttr (const std::string& attr_name, const Object& value)
+ {
+ the_item.setAttr(attr_name, value);
+ }
+
+ void delAttr (const std::string& attr_name)
+ {
+ the_item.delAttr(attr_name);
+ }
+
+ void delItem (const Object& key)
+ {
+ the_item.delItem(key);
+ }
+
+ bool operator==(const Object& o2) const
+ {
+ return the_item == o2;
+ }
+
+ bool operator!=(const Object& o2) const
+ {
+ return the_item != o2;
+ }
+
+ bool operator>=(const Object& o2) const
+ {
+ return the_item >= o2;
+ }
+
+ bool operator<=(const Object& o2) const
+ {
+ return the_item <= o2;
+ }
+
+ bool operator<(const Object& o2) const
+ {
+ return the_item < o2;
+ }
+
+ bool operator>(const Object& o2) const
+ {
+ return the_item > o2;
+ }
+ }; // end of seqref
+
+
+ // class SeqBase<T>
+ // ...the base class for all sequence types
+
+ template<TEMPLATE_TYPENAME T>
+ class SeqBase: public Object
+ {
+ public:
+ // STL definitions
+ typedef size_t size_type;
+ typedef seqref<T> reference;
+ typedef T const_reference;
+ typedef seqref<T>* pointer;
+ typedef int difference_type;
+ typedef T value_type; // TMM: 26Jun'01
+
+ virtual size_type max_size() const
+ {
+ return std::string::npos; // ?
+ }
+
+ virtual size_type capacity() const
+ {
+ return size();
+ }
+
+ virtual void swap(SeqBase<T>& c)
+ {
+ SeqBase<T> temp = c;
+ c = ptr();
+ set(temp.ptr());
+ }
+
+ virtual size_type size () const
+ {
+ return PySequence_Length (ptr());
+ }
+
+ explicit SeqBase<T> ()
+ :Object(PyTuple_New(0), true)
+ {
+ validate();
+ }
+
+ explicit SeqBase<T> (PyObject* pyob, bool owned=false)
+ : Object(pyob, owned)
+ {
+ validate();
+ }
+
+ SeqBase<T> (const Object& ob): Object(ob)
+ {
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+
+ SeqBase<T>& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ SeqBase<T>& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && PySequence_Check (pyob);
+ }
+
+ size_type length () const
+ {
+ return PySequence_Length (ptr());
+ }
+
+ // Element access
+ const T operator[](sequence_index_type index) const
+ {
+ return getItem(index);
+ }
+
+ seqref<T> operator[](sequence_index_type index)
+ {
+ return seqref<T>(*this, index);
+ }
+
+ virtual T getItem (sequence_index_type i) const
+ {
+ return T(asObject(PySequence_GetItem (ptr(), i)));
+ }
+
+ virtual void setItem (sequence_index_type i, const T& ob)
+ {
+ if (PySequence_SetItem (ptr(), i, *ob) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ SeqBase<T> repeat (int count) const
+ {
+ return SeqBase<T> (PySequence_Repeat (ptr(), count), true);
+ }
+
+ SeqBase<T> concat (const SeqBase<T>& other) const
+ {
+ return SeqBase<T> (PySequence_Concat(ptr(), *other), true);
+ }
+
+ // more STL compatability
+ const T front () const
+ {
+ return getItem(0);
+ }
+
+ seqref<T> front()
+ {
+ return seqref<T>(this, 0);
+ }
+
+ const T back () const
+ {
+ return getItem(size()-1);
+ }
+
+ seqref<T> back()
+ {
+ return seqref<T>(this, size()-1);
+ }
+
+ void verify_length(size_type required_size) const
+ {
+ if (size() != required_size)
+ throw IndexError ("Unexpected SeqBase<T> length.");
+ }
+
+ void verify_length(size_type min_size, size_type max_size) const
+ {
+ size_type n = size();
+ if (n < min_size || n > max_size)
+ throw IndexError ("Unexpected SeqBase<T> length.");
+ }
+
+ class iterator
+ : public random_access_iterator_parent(seqref<T>)
+ {
+ protected:
+ friend class SeqBase<T>;
+ SeqBase<T>* seq;
+ int count;
+
+ public:
+ ~iterator ()
+ {}
+
+ iterator ()
+ : seq( 0 )
+ , count( 0 )
+ {}
+
+ iterator (SeqBase<T>* s, int where)
+ : seq( s )
+ , count( where )
+ {}
+
+ iterator (const iterator& other)
+ : seq( other.seq )
+ , count( other.count )
+ {}
+
+ bool eql (const iterator& other) const
+ {
+ return (*seq == *other.seq) && (count == other.count);
+ }
+
+ bool neq (const iterator& other) const
+ {
+ return (*seq != *other.seq) || (count != other.count);
+ }
+
+ bool lss (const iterator& other) const
+ {
+ return (count < other.count);
+ }
+
+ bool gtr (const iterator& other) const
+ {
+ return (count > other.count);
+ }
+
+ bool leq (const iterator& other) const
+ {
+ return (count <= other.count);
+ }
+
+ bool geq (const iterator& other) const
+ {
+ return (count >= other.count);
+ }
+
+ seqref<T> operator*()
+ {
+ return seqref<T>(*seq, count);
+ }
+
+ seqref<T> operator[] (sequence_index_type i)
+ {
+ return seqref<T>(*seq, count + i);
+ }
+
+ iterator& operator=(const iterator& other)
+ {
+ if (this == &other) return *this;
+ seq = other.seq;
+ count = other.count;
+ return *this;
+ }
+
+ iterator operator+(int n) const
+ {
+ return iterator(seq, count + n);
+ }
+
+ iterator operator-(int n) const
+ {
+ return iterator(seq, count - n);
+ }
+
+ iterator& operator+=(int n)
+ {
+ count = count + n;
+ return *this;
+ }
+
+ iterator& operator-=(int n)
+ {
+ count = count - n;
+ return *this;
+ }
+
+ int operator-(const iterator& other) const
+ {
+ if (*seq != *other.seq)
+ throw RuntimeError ("SeqBase<T>::iterator comparison error");
+ return count - other.count;
+ }
+
+ // prefix ++
+ iterator& operator++ ()
+ { count++; return *this;}
+ // postfix ++
+ iterator operator++ (int)
+ { return iterator(seq, count++);}
+ // prefix --
+ iterator& operator-- ()
+ { count--; return *this;}
+ // postfix --
+ iterator operator-- (int)
+ { return iterator(seq, count--);}
+
+ std::string diagnose() const
+ {
+ std::OSTRSTREAM oss;
+ oss << "iterator diagnosis " << seq << ", " << count << std::ends;
+ return std::string(oss.str());
+ }
+ }; // end of class SeqBase<T>::iterator
+
+ iterator begin ()
+ {
+ return iterator(this, 0);
+ }
+
+ iterator end ()
+ {
+ return iterator(this, length());
+ }
+
+ class const_iterator
+ : public random_access_iterator_parent(const Object)
+ {
+ protected:
+ friend class SeqBase<T>;
+ const SeqBase<T>* seq;
+ sequence_index_type count;
+
+ public:
+ ~const_iterator ()
+ {}
+
+ const_iterator ()
+ : seq( 0 )
+ , count( 0 )
+ {}
+
+ const_iterator (const SeqBase<T>* s, int where)
+ : seq( s )
+ , count( where )
+ {}
+
+ const_iterator(const const_iterator& other)
+ : seq( other.seq )
+ , count( other.count )
+ {}
+
+ const T operator*() const
+ {
+ return seq->getItem(count);
+ }
+
+ const T operator[] (sequence_index_type i) const
+ {
+ return seq->getItem(count + i);
+ }
+
+ const_iterator& operator=(const const_iterator& other)
+ {
+ if (this == &other) return *this;
+ seq = other.seq;
+ count = other.count;
+ return *this;
+ }
+
+ const_iterator operator+(int n) const
+ {
+ return const_iterator(seq, count + n);
+ }
+
+ bool eql (const const_iterator& other) const
+ {
+ return (*seq == *other.seq) && (count == other.count);
+ }
+
+ bool neq (const const_iterator& other) const
+ {
+ return (*seq != *other.seq) || (count != other.count);
+ }
+
+ bool lss (const const_iterator& other) const
+ {
+ return (count < other.count);
+ }
+
+ bool gtr (const const_iterator& other) const
+ {
+ return (count > other.count);
+ }
+
+ bool leq (const const_iterator& other) const
+ {
+ return (count <= other.count);
+ }
+
+ bool geq (const const_iterator& other) const
+ {
+ return (count >= other.count);
+ }
+
+ const_iterator operator-(int n)
+ {
+ return const_iterator(seq, count - n);
+ }
+
+ const_iterator& operator+=(int n)
+ {
+ count = count + n;
+ return *this;
+ }
+
+ const_iterator& operator-=(int n)
+ {
+ count = count - n;
+ return *this;
+ }
+
+ int operator-(const const_iterator& other) const
+ {
+ if (*seq != *other.seq)
+ throw RuntimeError ("SeqBase<T>::const_iterator::- error");
+ return count - other.count;
+ }
+ // prefix ++
+ const_iterator& operator++ ()
+ { count++; return *this;}
+ // postfix ++
+ const_iterator operator++ (int)
+ { return const_iterator(seq, count++);}
+ // prefix --
+ const_iterator& operator-- ()
+ { count--; return *this;}
+ // postfix --
+ const_iterator operator-- (int)
+ { return const_iterator(seq, count--);}
+ }; // end of class SeqBase<T>::const_iterator
+
+ const_iterator begin () const
+ {
+ return const_iterator(this, 0);
+ }
+
+ const_iterator end () const
+ {
+ return const_iterator(this, length());
+ }
+ };
+
+ // Here's an important typedef you might miss if reading too fast...
+ typedef SeqBase<Object> Sequence;
+
+ template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator< (const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator> (const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator<=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator>=(const EXPLICIT_TYPENAME SeqBase<T>::iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::iterator& right);
+
+ template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator< (const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator> (const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator<=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator>=(const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& left, const EXPLICIT_TYPENAME SeqBase<T>::const_iterator& right);
+
+
+ extern bool operator==(const Sequence::iterator& left, const Sequence::iterator& right);
+ extern bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right);
+ extern bool operator< (const Sequence::iterator& left, const Sequence::iterator& right);
+ extern bool operator> (const Sequence::iterator& left, const Sequence::iterator& right);
+ extern bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right);
+ extern bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right);
+
+ extern bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+ extern bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+ extern bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+ extern bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+ extern bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+ extern bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right);
+
+ // ==================================================
+ // class Char
+ // Python strings return strings as individual elements.
+ // I'll try having a class Char which is a String of length 1
+ //
+ typedef std::basic_string<Py_UNICODE> unicodestring;
+ extern Py_UNICODE unicode_null_string[1];
+
+ class Char: public Object
+ {
+ public:
+ explicit Char (PyObject *pyob, bool owned = false): Object(pyob, owned)
+ {
+ validate();
+ }
+
+ Char (const Object& ob): Object(ob)
+ {
+ validate();
+ }
+
+ Char (const std::string& v = "")
+ :Object(PyString_FromStringAndSize (const_cast<char*>(v.c_str()),1), true)
+ {
+ validate();
+ }
+
+ Char (char v)
+ : Object(PyString_FromStringAndSize (&v, 1), true)
+ {
+ validate();
+ }
+
+ Char (Py_UNICODE v)
+ : Object(PyUnicode_FromUnicode (&v, 1), true)
+ {
+ validate();
+ }
+ // Assignment acquires new ownership of pointer
+ Char& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Char& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob)) && PySequence_Length (pyob) == 1;
+ }
+
+ // Assignment from C string
+ Char& operator= (const std::string& v)
+ {
+ set(PyString_FromStringAndSize (const_cast<char*>(v.c_str()),1), true);
+ return *this;
+ }
+
+ Char& operator= (char v)
+ {
+ set(PyString_FromStringAndSize (&v, 1), true);
+ return *this;
+ }
+
+ Char& operator= (const unicodestring& v)
+ {
+ set(PyUnicode_FromUnicode (const_cast<Py_UNICODE*>(v.data()),1), true);
+ return *this;
+ }
+
+ Char& operator= (Py_UNICODE v)
+ {
+ set(PyUnicode_FromUnicode (&v, 1), true);
+ return *this;
+ }
+
+ // Conversion
+ operator String() const;
+
+ operator std::string () const
+ {
+ return std::string(PyString_AsString (ptr()));
+ }
+ };
+
+ class String: public SeqBase<Char>
+ {
+ public:
+ virtual size_type capacity() const
+ {
+ return max_size();
+ }
+
+ explicit String (PyObject *pyob, bool owned = false): SeqBase<Char>(pyob, owned)
+ {
+ validate();
+ }
+
+ String (const Object& ob): SeqBase<Char>(ob)
+ {
+ validate();
+ }
+
+ String()
+ : SeqBase<Char>( PyString_FromStringAndSize( "", 0 ), true )
+ {
+ validate();
+ }
+
+ String( const std::string& v )
+ : SeqBase<Char>( PyString_FromStringAndSize( const_cast<char*>(v.data()),
+ static_cast<int>( v.length() ) ), true )
+ {
+ validate();
+ }
+
+ String( const char *s, const char *encoding, const char *error="strict" )
+ : SeqBase<Char>( PyUnicode_Decode( s, strlen( s ), encoding, error ), true )
+ {
+ validate();
+ }
+
+ String( const char *s, int len, const char *encoding, const char *error="strict" )
+ : SeqBase<Char>( PyUnicode_Decode( s, len, encoding, error ), true )
+ {
+ validate();
+ }
+
+ String( const std::string &s, const char *encoding, const char *error="strict" )
+ : SeqBase<Char>( PyUnicode_Decode( s.c_str(), s.length(), encoding, error ), true )
+ {
+ validate();
+ }
+
+ String( const std::string& v, std::string::size_type vsize )
+ : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v.data()),
+ static_cast<int>( vsize ) ), true)
+ {
+ validate();
+ }
+
+ String( const char *v, int vsize )
+ : SeqBase<Char>(PyString_FromStringAndSize( const_cast<char*>(v), vsize ), true )
+ {
+ validate();
+ }
+
+ String( const char* v )
+ : SeqBase<Char>( PyString_FromString( v ), true )
+ {
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+ String& operator= ( const Object& rhs )
+ {
+ return *this = *rhs;
+ }
+
+ String& operator= (PyObject* rhsp)
+ {
+ if( ptr() == rhsp )
+ return *this;
+ set (rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && (Py::_String_Check(pyob) || Py::_Unicode_Check(pyob));
+ }
+
+ // Assignment from C string
+ String& operator= (const std::string& v)
+ {
+ set( PyString_FromStringAndSize( const_cast<char*>( v.data() ),
+ static_cast<int>( v.length() ) ), true );
+ return *this;
+ }
+ String& operator= (const unicodestring& v)
+ {
+ set( PyUnicode_FromUnicode( const_cast<Py_UNICODE*>( v.data() ),
+ static_cast<int>( v.length() ) ), true );
+ return *this;
+ }
+
+
+ // Encode
+ String encode( const char *encoding, const char *error="strict" )
+ {
+ if( isUnicode() )
+ {
+ return String( PyUnicode_AsEncodedString( ptr(), encoding, error ) );
+ }
+ else
+ {
+ return String( PyString_AsEncodedObject( ptr(), encoding, error ) );
+ }
+ }
+
+ String decode( const char *encoding, const char *error="strict" )
+ {
+ return Object( PyString_AsDecodedObject( ptr(), encoding, error ) );
+ }
+
+ // Queries
+ virtual size_type size () const
+ {
+ if( isUnicode() )
+ {
+ return static_cast<size_type>( PyUnicode_GET_SIZE (ptr()) );
+ }
+ else
+ {
+ return static_cast<size_type>( PyString_Size (ptr()) );
+ }
+ }
+
+ operator std::string () const
+ {
+ return as_std_string();
+ }
+
+ std::string as_std_string() const
+ {
+ if( isUnicode() )
+ {
+ throw TypeError("cannot return std::string from Unicode object");
+ }
+ else
+ {
+ return std::string( PyString_AsString( ptr() ), static_cast<size_type>( PyString_Size( ptr() ) ) );
+ }
+ }
+
+ unicodestring as_unicodestring() const
+ {
+ if( isUnicode() )
+ {
+ return unicodestring( PyUnicode_AS_UNICODE( ptr() ),
+ static_cast<size_type>( PyUnicode_GET_SIZE( ptr() ) ) );
+ }
+ else
+ {
+ throw TypeError("can only return unicodestring from Unicode object");
+ }
+ }
+ };
+
+ // ==================================================
+ // class Tuple
+ class Tuple: public Sequence
+ {
+ public:
+ virtual void setItem (sequence_index_type offset, const Object&ob)
+ {
+ // note PyTuple_SetItem is a thief...
+ if(PyTuple_SetItem (ptr(), offset, new_reference_to(ob)) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ // Constructor
+ explicit Tuple (PyObject *pyob, bool owned = false): Sequence (pyob, owned)
+ {
+ validate();
+ }
+
+ Tuple (const Object& ob): Sequence(ob)
+ {
+ validate();
+ }
+
+ // New tuple of a given size
+ explicit Tuple (int size = 0)
+ {
+ set(PyTuple_New (size), true);
+ validate ();
+ for (sequence_index_type i=0; i < size; i++)
+ {
+ if(PyTuple_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1)
+ {
+ throw Exception();
+ }
+ }
+ }
+ // Tuple from any sequence
+ explicit Tuple (const Sequence& s)
+ {
+ sequence_index_type limit( sequence_index_type( s.length() ) );
+
+ set(PyTuple_New (limit), true);
+ validate();
+
+ for(sequence_index_type i=0; i < limit; i++)
+ {
+ if(PyTuple_SetItem (ptr(), i, new_reference_to(s[i])) == -1)
+ {
+ throw Exception();
+ }
+ }
+ }
+ // Assignment acquires new ownership of pointer
+
+ Tuple& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Tuple& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Tuple_Check (pyob);
+ }
+
+ Tuple getSlice (int i, int j) const
+ {
+ return Tuple (PySequence_GetSlice (ptr(), i, j), true);
+ }
+
+ };
+
+ // ==================================================
+ // class List
+
+ class List: public Sequence
+ {
+ public:
+ // Constructor
+ explicit List (PyObject *pyob, bool owned = false): Sequence(pyob, owned)
+ {
+ validate();
+ }
+ List (const Object& ob): Sequence(ob)
+ {
+ validate();
+ }
+ // Creation at a fixed size
+ List (int size = 0)
+ {
+ set(PyList_New (size), true);
+ validate();
+ for (sequence_index_type i=0; i < size; i++)
+ {
+ if(PyList_SetItem (ptr(), i, new_reference_to(Py::_None())) == -1)
+ {
+ throw Exception();
+ }
+ }
+ }
+
+ // List from a sequence
+ List (const Sequence& s): Sequence()
+ {
+ int n = s.length();
+ set(PyList_New (n), true);
+ validate();
+ for (sequence_index_type i=0; i < n; i++)
+ {
+ if(PyList_SetItem (ptr(), i, new_reference_to(s[i])) == -1)
+ {
+ throw Exception();
+ }
+ }
+ }
+
+ virtual size_type capacity() const
+ {
+ return max_size();
+ }
+ // Assignment acquires new ownership of pointer
+
+ List& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ List& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_List_Check (pyob);
+ }
+
+ List getSlice (int i, int j) const
+ {
+ return List (PyList_GetSlice (ptr(), i, j), true);
+ }
+
+ void setSlice (int i, int j, const Object& v)
+ {
+ if(PyList_SetSlice (ptr(), i, j, *v) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void append (const Object& ob)
+ {
+ if(PyList_Append (ptr(), *ob) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void insert (int i, const Object& ob)
+ {
+ if(PyList_Insert (ptr(), i, *ob) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void sort ()
+ {
+ if(PyList_Sort(ptr()) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void reverse ()
+ {
+ if(PyList_Reverse(ptr()) == -1)
+ {
+ throw Exception();
+ }
+ }
+ };
+
+
+ // Mappings
+ // ==================================================
+ template<TEMPLATE_TYPENAME T>
+ class mapref
+ {
+ protected:
+ MapBase<T>& s; // the map
+ Object key; // item key
+ T the_item;
+
+ public:
+ mapref<T> (MapBase<T>& map, const std::string& k)
+ : s(map), the_item()
+ {
+ key = String(k);
+ if(map.hasKey(key)) the_item = map.getItem(key);
+ };
+
+ mapref<T> (MapBase<T>& map, const Object& k)
+ : s(map), key(k), the_item()
+ {
+ if(map.hasKey(key)) the_item = map.getItem(key);
+ };
+
+ ~mapref()
+ {}
+
+ // MapBase<T> stuff
+ // lvalue
+ mapref<T>& operator=(const mapref<T>& other)
+ {
+ if(this == &other) return *this;
+ the_item = other.the_item;
+ s.setItem(key, other.the_item);
+ return *this;
+ };
+
+ mapref<T>& operator= (const T& ob)
+ {
+ the_item = ob;
+ s.setItem (key, ob);
+ return *this;
+ }
+
+ // rvalue
+ operator T() const
+ {
+ return the_item;
+ }
+
+ // forward everything else to the_item
+ PyObject* ptr () const
+ {
+ return the_item.ptr();
+ }
+
+ int reference_count () const
+ { // the mapref count
+ return the_item.reference_count();
+ }
+
+ Type type () const
+ {
+ return the_item.type();
+ }
+
+ String str () const
+ {
+ return the_item.str();
+ }
+
+ String repr () const
+ {
+ return the_item.repr();
+ }
+
+ bool hasAttr (const std::string& attr_name) const
+ {
+ return the_item.hasAttr(attr_name);
+ }
+
+ Object getAttr (const std::string& attr_name) const
+ {
+ return the_item.getAttr(attr_name);
+ }
+
+ Object getItem (const Object& k) const
+ {
+ return the_item.getItem(k);
+ }
+
+ long hashValue () const
+ {
+ return the_item.hashValue();
+ }
+
+ bool isCallable () const
+ {
+ return the_item.isCallable();
+ }
+
+ bool isList () const
+ {
+ return the_item.isList();
+ }
+
+ bool isMapping () const
+ {
+ return the_item.isMapping();
+ }
+
+ bool isNumeric () const
+ {
+ return the_item.isNumeric();
+ }
+
+ bool isSequence () const
+ {
+ return the_item.isSequence();
+ }
+
+ bool isTrue () const
+ {
+ return the_item.isTrue();
+ }
+
+ bool isType (const Type& t) const
+ {
+ return the_item.isType (t);
+ }
+
+ bool isTuple() const
+ {
+ return the_item.isTuple();
+ }
+
+ bool isString() const
+ {
+ return the_item.isString();
+ }
+
+ // Commands
+ void setAttr (const std::string& attr_name, const Object& value)
+ {
+ the_item.setAttr(attr_name, value);
+ }
+
+ void delAttr (const std::string& attr_name)
+ {
+ the_item.delAttr(attr_name);
+ }
+
+ void delItem (const Object& k)
+ {
+ the_item.delItem(k);
+ }
+ }; // end of mapref
+
+ // TMM: now for mapref<T>
+ template< class T >
+ bool operator==(const mapref<T>& left, const mapref<T>& right)
+ {
+ return true; // NOT completed.
+ }
+
+ template< class T >
+ bool operator!=(const mapref<T>& left, const mapref<T>& right)
+ {
+ return true; // not completed.
+ }
+
+ template<TEMPLATE_TYPENAME T>
+ class MapBase: public Object
+ {
+ protected:
+ explicit MapBase<T>()
+ {}
+ public:
+ // reference: proxy class for implementing []
+ // TMM: 26Jun'01 - the types
+ // If you assume that Python mapping is a hash_map...
+ // hash_map::value_type is not assignable, but
+ // (*it).second = data must be a valid expression
+ typedef size_t size_type;
+ typedef Object key_type;
+ typedef mapref<T> data_type;
+ typedef std::pair< const T, T > value_type;
+ typedef std::pair< const T, mapref<T> > reference;
+ typedef const std::pair< const T, const T > const_reference;
+ typedef std::pair< const T, mapref<T> > pointer;
+
+ // Constructor
+ explicit MapBase<T> (PyObject *pyob, bool owned = false): Object(pyob, owned)
+ {
+ validate();
+ }
+
+ // TMM: 02Jul'01 - changed MapBase<T> to Object in next line
+ MapBase<T> (const Object& ob): Object(ob)
+ {
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+ MapBase<T>& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ MapBase<T>& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && PyMapping_Check(pyob);
+ }
+
+ // Clear -- PyMapping Clear is missing
+ //
+
+ void clear ()
+ {
+ List k = keys();
+ for(List::iterator i = k.begin(); i != k.end(); i++)
+ {
+ delItem(*i);
+ }
+ }
+
+ virtual size_type size() const
+ {
+ return PyMapping_Length (ptr());
+ }
+
+ // Element Access
+ T operator[](const std::string& key) const
+ {
+ return getItem(key);
+ }
+
+ T operator[](const Object& key) const
+ {
+ return getItem(key);
+ }
+
+ mapref<T> operator[](const std::string& key)
+ {
+ return mapref<T>(*this, key);
+ }
+
+ mapref<T> operator[](const Object& key)
+ {
+ return mapref<T>(*this, key);
+ }
+
+ int length () const
+ {
+ return PyMapping_Length (ptr());
+ }
+
+ bool hasKey (const std::string& s) const
+ {
+ return PyMapping_HasKeyString (ptr(),const_cast<char*>(s.c_str())) != 0;
+ }
+
+ bool hasKey (const Object& s) const
+ {
+ return PyMapping_HasKey (ptr(), s.ptr()) != 0;
+ }
+
+ T getItem (const std::string& s) const
+ {
+ return T(
+ asObject(PyMapping_GetItemString (ptr(),const_cast<char*>(s.c_str())))
+ );
+ }
+
+ T getItem (const Object& s) const
+ {
+ return T(
+ asObject(PyObject_GetItem (ptr(), s.ptr()))
+ );
+ }
+
+ virtual void setItem (const char *s, const Object& ob)
+ {
+ if (PyMapping_SetItemString (ptr(), const_cast<char*>(s), *ob) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ virtual void setItem (const std::string& s, const Object& ob)
+ {
+ if (PyMapping_SetItemString (ptr(), const_cast<char*>(s.c_str()), *ob) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ virtual void setItem (const Object& s, const Object& ob)
+ {
+ if (PyObject_SetItem (ptr(), s.ptr(), ob.ptr()) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void delItem (const std::string& s)
+ {
+ if (PyMapping_DelItemString (ptr(), const_cast<char*>(s.c_str())) == -1)
+ {
+ throw Exception();
+ }
+ }
+
+ void delItem (const Object& s)
+ {
+ if (PyMapping_DelItem (ptr(), *s) == -1)
+ {
+ throw Exception();
+ }
+ }
+ // Queries
+ List keys () const
+ {
+ return List(PyMapping_Keys(ptr()), true);
+ }
+
+ List values () const
+ { // each returned item is a (key, value) pair
+ return List(PyMapping_Values(ptr()), true);
+ }
+
+ List items () const
+ {
+ return List(PyMapping_Items(ptr()), true);
+ }
+
+ // iterators for MapBase<T>
+ // Added by TMM: 2Jul'01 - NOT COMPLETED
+ // There is still a bug. I decided to stop, before fixing the bug, because
+ // this can't be halfway efficient until Python gets built-in iterators.
+ // My current soln is to iterate over the map by getting a copy of its keys
+ // and iterating over that. Not a good solution.
+
+ // The iterator holds a MapBase<T>* rather than a MapBase<T> because that's
+ // how the sequence iterator is implemented and it works. But it does seem
+ // odd to me - we are iterating over the map object, not the reference.
+
+#if 0 // here is the test code with which I found the (still existing) bug
+ typedef cxx::Dict d_t;
+ d_t d;
+ cxx::String s1("blah");
+ cxx::String s2("gorf");
+ d[ "one" ] = s1;
+ d[ "two" ] = s1;
+ d[ "three" ] = s2;
+ d[ "four" ] = s2;
+
+ d_t::iterator it;
+ it = d.begin(); // this (using the assignment operator) is causing
+ // a problem; if I just use the copy ctor it works fine.
+ for( ; it != d.end(); ++it )
+ {
+ d_t::value_type vt( *it );
+ cxx::String rs = vt.second.repr();
+ std::string ls = rs.operator std::string();
+ fprintf( stderr, "%s\n", ls );
+ }
+#endif // 0
+
+ class iterator
+ {
+ // : public forward_iterator_parent( std::pair<const T,T> ) {
+ protected:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::pair< const T, T > value_type;
+ typedef int difference_type;
+ typedef std::pair< const T, mapref<T> > pointer;
+ typedef std::pair< const T, mapref<T> > reference;
+
+ friend class MapBase<T>;
+ //
+ MapBase<T>* map;
+ List keys; // for iterating over the map
+ List::iterator pos; // index into the keys
+
+ public:
+ ~iterator ()
+ {}
+
+ iterator ()
+ : map( 0 )
+ , keys()
+ , pos()
+ {}
+
+ iterator (MapBase<T>* m, bool end = false )
+ : map( m )
+ , keys( m->keys() )
+ , pos( end ? keys.end() : keys.begin() )
+ {}
+
+ iterator (const iterator& other)
+ : map( other.map )
+ , keys( other.keys )
+ , pos( other.pos )
+ {}
+
+ reference operator*()
+ {
+ Object key = *pos;
+ return std::make_pair(key, mapref<T>(*map,key));
+ }
+
+ iterator& operator=(const iterator& other)
+ {
+ if (this == &other)
+ return *this;
+ map = other.map;
+ keys = other.keys;
+ pos = other.pos;
+ return *this;
+ }
+
+ bool eql(const iterator& right) const
+ {
+ return *map == *right.map && pos == right.pos;
+ }
+ bool neq( const iterator& right ) const
+ {
+ return *map != *right.map || pos != right.pos;
+ }
+
+ // pointer operator->() {
+ // return ;
+ // }
+
+ // prefix ++
+ iterator& operator++ ()
+ { pos++; return *this;}
+ // postfix ++
+ iterator operator++ (int)
+ { return iterator(map, keys, pos++);}
+ // prefix --
+ iterator& operator-- ()
+ { pos--; return *this;}
+ // postfix --
+ iterator operator-- (int)
+ { return iterator(map, keys, pos--);}
+
+ std::string diagnose() const
+ {
+ std::OSTRSTREAM oss;
+ oss << "iterator diagnosis " << map << ", " << pos << std::ends;
+ return std::string(oss.str());
+ }
+ }; // end of class MapBase<T>::iterator
+
+ iterator begin ()
+ {
+ return iterator(this);
+ }
+
+ iterator end ()
+ {
+ return iterator(this, true);
+ }
+
+ class const_iterator
+ {
+ protected:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef const std::pair< const T, T > value_type;
+ typedef int difference_type;
+ typedef const std::pair< const T, T > pointer;
+ typedef const std::pair< const T, T > reference;
+
+ friend class MapBase<T>;
+ const MapBase<T>* map;
+ List keys; // for iterating over the map
+ List::iterator pos; // index into the keys
+
+ public:
+ ~const_iterator ()
+ {}
+
+ const_iterator ()
+ : map( 0 )
+ , keys()
+ , pos()
+ {}
+
+ const_iterator (const MapBase<T>* m, List k, List::iterator p )
+ : map( m )
+ , keys( k )
+ , pos( p )
+ {}
+
+ const_iterator(const const_iterator& other)
+ : map( other.map )
+ , keys( other.keys )
+ , pos( other.pos )
+ {}
+
+ bool eql(const const_iterator& right) const
+ {
+ return *map == *right.map && pos == right.pos;
+ }
+ bool neq( const const_iterator& right ) const
+ {
+ return *map != *right.map || pos != right.pos;
+ }
+
+
+ // const_reference operator*() {
+ // Object key = *pos;
+ // return std::make_pair( key, map->[key] );
+ // GCC < 3 barfes on this line at the '['.
+ // }
+
+ const_iterator& operator=(const const_iterator& other)
+ {
+ if (this == &other) return *this;
+ map = other.map;
+ keys = other.keys;
+ pos = other.pos;
+ return *this;
+ }
+
+ // prefix ++
+ const_iterator& operator++ ()
+ { pos++; return *this;}
+ // postfix ++
+ const_iterator operator++ (int)
+ { return const_iterator(map, keys, pos++);}
+ // prefix --
+ const_iterator& operator-- ()
+ { pos--; return *this;}
+ // postfix --
+ const_iterator operator-- (int)
+ { return const_iterator(map, keys, pos--);}
+ }; // end of class MapBase<T>::const_iterator
+
+ const_iterator begin () const
+ {
+ return const_iterator(this, 0);
+ }
+
+ const_iterator end () const
+ {
+ return const_iterator(this, length());
+ }
+
+ }; // end of MapBase<T>
+
+ typedef MapBase<Object> Mapping;
+
+ template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME MapBase<T>::iterator& left, const EXPLICIT_TYPENAME MapBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME MapBase<T>::iterator& left, const EXPLICIT_TYPENAME MapBase<T>::iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator==(const EXPLICIT_TYPENAME MapBase<T>::const_iterator& left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator& right);
+ template <TEMPLATE_TYPENAME T> bool operator!=(const EXPLICIT_TYPENAME MapBase<T>::const_iterator& left, const EXPLICIT_TYPENAME MapBase<T>::const_iterator& right);
+
+ extern bool operator==(const Mapping::iterator& left, const Mapping::iterator& right);
+ extern bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right);
+ extern bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right);
+ extern bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right);
+
+
+ // ==================================================
+ // class Dict
+ class Dict: public Mapping
+ {
+ public:
+ // Constructor
+ explicit Dict (PyObject *pyob, bool owned=false): Mapping (pyob, owned)
+ {
+ validate();
+ }
+ Dict (const Dict& ob): Mapping(ob)
+ {
+ validate();
+ }
+ // Creation
+ Dict ()
+ {
+ set(PyDict_New (), true);
+ validate();
+ }
+ // Assignment acquires new ownership of pointer
+
+ Dict& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Dict& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set(rhsp);
+ return *this;
+ }
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && Py::_Dict_Check (pyob);
+ }
+ };
+
+ class Callable: public Object
+ {
+ protected:
+ explicit Callable (): Object()
+ {}
+ public:
+ // Constructor
+ explicit Callable (PyObject *pyob, bool owned = false): Object (pyob, owned)
+ {
+ validate();
+ }
+
+ Callable (const Object& ob): Object(ob)
+ {
+ validate();
+ }
+
+ // Assignment acquires new ownership of pointer
+
+ Callable& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Callable& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set (rhsp);
+ return *this;
+ }
+
+ // Membership
+ virtual bool accepts (PyObject *pyob) const
+ {
+ return pyob && PyCallable_Check (pyob);
+ }
+
+ // Call
+ Object apply(const Tuple& args) const
+ {
+ return asObject(PyObject_CallObject(ptr(), args.ptr()));
+ }
+
+ // Call with keywords
+ Object apply(const Tuple& args, const Dict& kw) const
+ {
+ return asObject( PyEval_CallObjectWithKeywords( ptr(), args.ptr(), kw.ptr() ) );
+ }
+
+ Object apply(PyObject* pargs = 0) const
+ {
+ return apply (Tuple(pargs));
+ }
+ };
+
+ class Module: public Object
+ {
+ public:
+ explicit Module (PyObject* pyob, bool owned = false): Object (pyob, owned)
+ {
+ validate();
+ }
+
+ // Construct from module name
+ explicit Module (const std::string&s): Object()
+ {
+ PyObject *m = PyImport_AddModule( const_cast<char *>(s.c_str()) );
+ set( m, false );
+ validate ();
+ }
+
+ // Copy constructor acquires new ownership of pointer
+ Module (const Module& ob): Object(*ob)
+ {
+ validate();
+ }
+
+ Module& operator= (const Object& rhs)
+ {
+ return (*this = *rhs);
+ }
+
+ Module& operator= (PyObject* rhsp)
+ {
+ if(ptr() == rhsp) return *this;
+ set(rhsp);
+ return *this;
+ }
+
+ Dict getDict()
+ {
+ return Dict(PyModule_GetDict(ptr()));
+ // Caution -- PyModule_GetDict returns borrowed reference!
+ }
+ };
+
+ // Numeric interface
+ inline Object operator+ (const Object& a)
+ {
+ return asObject(PyNumber_Positive(*a));
+ }
+ inline Object operator- (const Object& a)
+ {
+ return asObject(PyNumber_Negative(*a));
+ }
+
+ inline Object abs(const Object& a)
+ {
+ return asObject(PyNumber_Absolute(*a));
+ }
+
+ inline std::pair<Object,Object> coerce(const Object& a, const Object& b)
+ {
+ PyObject *p1, *p2;
+ p1 = *a;
+ p2 = *b;
+ if(PyNumber_Coerce(&p1,&p2) == -1)
+ {
+ throw Exception();
+ }
+ return std::pair<Object,Object>(asObject(p1), asObject(p2));
+ }
+
+ inline Object operator+ (const Object& a, const Object& b)
+ {
+ return asObject(PyNumber_Add(*a, *b));
+ }
+ inline Object operator+ (const Object& a, int j)
+ {
+ return asObject(PyNumber_Add(*a, *Int(j)));
+ }
+ inline Object operator+ (const Object& a, double v)
+ {
+ return asObject(PyNumber_Add(*a, *Float(v)));
+ }
+ inline Object operator+ (int j, const Object& b)
+ {
+ return asObject(PyNumber_Add(*Int(j), *b));
+ }
+ inline Object operator+ (double v, const Object& b)
+ {
+ return asObject(PyNumber_Add(*Float(v), *b));
+ }
+
+ inline Object operator- (const Object& a, const Object& b)
+ {
+ return asObject(PyNumber_Subtract(*a, *b));
+ }
+ inline Object operator- (const Object& a, int j)
+ {
+ return asObject(PyNumber_Subtract(*a, *Int(j)));
+ }
+ inline Object operator- (const Object& a, double v)
+ {
+ return asObject(PyNumber_Subtract(*a, *Float(v)));
+ }
+ inline Object operator- (int j, const Object& b)
+ {
+ return asObject(PyNumber_Subtract(*Int(j), *b));
+ }
+ inline Object operator- (double v, const Object& b)
+ {
+ return asObject(PyNumber_Subtract(*Float(v), *b));
+ }
+
+ inline Object operator* (const Object& a, const Object& b)
+ {
+ return asObject(PyNumber_Multiply(*a, *b));
+ }
+ inline Object operator* (const Object& a, int j)
+ {
+ return asObject(PyNumber_Multiply(*a, *Int(j)));
+ }
+ inline Object operator* (const Object& a, double v)
+ {
+ return asObject(PyNumber_Multiply(*a, *Float(v)));
+ }
+ inline Object operator* (int j, const Object& b)
+ {
+ return asObject(PyNumber_Multiply(*Int(j), *b));
+ }
+ inline Object operator* (double v, const Object& b)
+ {
+ return asObject(PyNumber_Multiply(*Float(v), *b));
+ }
+
+ inline Object operator/ (const Object& a, const Object& b)
+ {
+ return asObject(PyNumber_Divide(*a, *b));
+ }
+ inline Object operator/ (const Object& a, int j)
+ {
+ return asObject(PyNumber_Divide(*a, *Int(j)));
+ }
+ inline Object operator/ (const Object& a, double v)
+ {
+ return asObject(PyNumber_Divide(*a, *Float(v)));
+ }
+ inline Object operator/ (int j, const Object& b)
+ {
+ return asObject(PyNumber_Divide(*Int(j), *b));
+ }
+ inline Object operator/ (double v, const Object& b)
+ {
+ return asObject(PyNumber_Divide(*Float(v), *b));
+ }
+
+ inline Object operator% (const Object& a, const Object& b)
+ {
+ return asObject(PyNumber_Remainder(*a, *b));
+ }
+ inline Object operator% (const Object& a, int j)
+ {
+ return asObject(PyNumber_Remainder(*a, *Int(j)));
+ }
+ inline Object operator% (const Object& a, double v)
+ {
+ return asObject(PyNumber_Remainder(*a, *Float(v)));
+ }
+ inline Object operator% (int j, const Object& b)
+ {
+ return asObject(PyNumber_Remainder(*Int(j), *b));
+ }
+ inline Object operator% (double v, const Object& b)
+ {
+ return asObject(PyNumber_Remainder(*Float(v), *b));
+ }
+
+ inline Object type(const Exception&) // return the type of the error
+ {
+ PyObject *ptype, *pvalue, *ptrace;
+ PyErr_Fetch(&ptype, &pvalue, &ptrace);
+ Object result(ptype);
+ PyErr_Restore(ptype, pvalue, ptrace);
+ return result;
+ }
+
+ inline Object value(const Exception&) // return the value of the error
+ {
+ PyObject *ptype, *pvalue, *ptrace;
+ PyErr_Fetch(&ptype, &pvalue, &ptrace);
+ Object result;
+ if(pvalue) result = pvalue;
+ PyErr_Restore(ptype, pvalue, ptrace);
+ return result;
+ }
+
+ inline Object trace(const Exception&) // return the traceback of the error
+ {
+ PyObject *ptype, *pvalue, *ptrace;
+ PyErr_Fetch(&ptype, &pvalue, &ptrace);
+ Object result;
+ if(ptrace) result = ptrace;
+ PyErr_Restore(ptype, pvalue, ptrace);
+ return result;
+ }
+
+
+
+template<TEMPLATE_TYPENAME T>
+String seqref<T>::str () const
+ {
+ return the_item.str();
+ }
+
+template<TEMPLATE_TYPENAME T>
+String seqref<T>::repr () const
+ {
+ return the_item.repr();
+ }
+
+
+ } // namespace Py
+#endif // __CXX_Objects__h
diff --git a/lib/kross/python/cxx/PyCXX.html b/lib/kross/python/cxx/PyCXX.html
new file mode 100644
index 00000000..566974c1
--- /dev/null
+++ b/lib/kross/python/cxx/PyCXX.html
@@ -0,0 +1,2131 @@
+<html>
+
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<title>Writing Python Extensions in C++</title>
+<style>
+H1, H2, H3, H4 {color: #000099;
+ background-color: lightskyblue}
+h3 {position: relative; left: 20px}
+
+p {position: relative; left: 20px; margin-right: 20px}
+pre {color: #0000cc; background-color: #eeeeee; position: relative; left: 40px; margin-right: 80px;
+ border-style: solid; border-color: black; border-width: thin}
+kbd {color: #990000}
+p cite, ol cite, ul cite {font-family: monospace; font-style: normal; font-size: normal}
+li var, pre var, p var, kbd var {color: #009900; font-style: italic}
+li samp, pre samp, p samp, kbd samp {color: #009900; font-weight: bold}
+li p {position: relative; left: 0}
+table { position: relative; left: 20px; border: solid #888888 1px; background-color: #eeeeee}
+table th {border: solid #888888 1px; background-color: #88dd88; color: black}
+table td {border: solid #888888 1px}
+table td.code {border: solid #888888 1px;font-family: monospace; font-style: normal; font-size: normal}
+p.param {background-color: #eeeeee; border-top: lightskyblue solid 4}
+</style>
+
+</head>
+
+<body bgcolor="#FFFFFF">
+
+<h1 ALIGN="center">Writing Python Extensions in C++</h1>
+
+<p ALIGN="CENTER">Barry Scott<br>
+Reading, Berkshire, England<br>
+<a href="mailto:[email protected]">[email protected]</a><br>
+</p>
+
+<p ALIGN="CENTER">Paul F. Dubois, <a href="mailto:[email protected]">[email protected]</a><br>
+Lawrence Livermore National Laboratory<br>
+Livermore, California, U.S.A.</p>
+
+
+<p>PyCXX is designed to make it easier to extend Python with C++</p>
+
+
+<p>PyCXX is a set of C++ facilities to make it easier to write Python extensions.
+The chief way in which PyCXX makes it easier to write Python extensions is that it greatly
+increases the probability that your program will not make a reference-counting error and
+will not have to continually check error returns from the Python C API. PyCXX
+integrates Python with C++ in these ways: </p>
+
+<ul>
+ <li>C++ exception handling is relied on to detect errors and clean up. In a complicated
+ function this is often a tremendous problem when writing in C. With PyCXX, we let the
+ compiler keep track of what objects need to be dereferenced when an error occurs.
+ <li>The Standard Template Library (STL) and its many algorithms plug and play with Python
+ containers such as lists and tuples.
+ <li>The optional CXX_Extensions facility allows you to replace the clumsy C tables with
+ objects and method calls that define your modules and extension objects.
+</ul>
+
+<h3>Download and Installation</h3>
+
+<p>Download PyCXX from <a href="http://sourceforge.net/projects/cxx/">http://sourceforge.net/projects/cxx/</a>.</p>
+
+<p>The distribution layout is:</p>
+<table>
+<tr><th>Directory</th><th>Description</th></tr>
+<tr><td class=code>.</td><td>Makefile for Unix and Windows, Release documentation</td>
+<tr><td class=code>./CXX</td><td>Header files</td>
+<tr><td class=code>./Src</td><td>Source files</td>
+<tr><td class=code>./Doc</td><td>Documentation</td>
+<tr><td class=code>./Demo</td><td>Testing and Demonstartion files</td>
+</table>
+
+<p>To use PyCXX you use its include files and add its source routines to your module.</p>
+
+<p>Installation:</p>
+<ul>
+<li>Install the PyCXX files into a directory of your choice. For example:<br>
+Windows: <cite>C:\PyCXX</cite><br>
+Unix: <cite>/usr/local/PyCXX</cite>
+<li>Tell your compiler where the PyCXX header files are:<br>
+Windows: <cite>cl /I=C:\PyCXX ...</cite><br>
+Unix: <cite>g++ -I/usr/local/PyCXX ...</cite>
+<li>Include PyCXX headers files in your code using the CXX prefix:<br>
+<cite>#include &quot;CXX/Object.hxx&quot;</cite>
+</ul>
+
+<p>The header file CXX/config.h may need to be adjusted for the
+compiler you use. As of this writing, only a fairly obscure reference to part of the
+standard library needs this adjustment. Unlike prior releases, PyCXX now assumes namespace
+support and a standard C++ library. </p>
+
+<h3>Use of namespaces</h3>
+
+<p>All PyCXX assets are in namespace &quot;Py&quot;. You need to include
+the Py:: prefix when referring to them, or include the statement:</p>
+
+<p>using namespace Py;</p>
+
+<h2>Wrappers for standard objects: CXX_Objects.h</h2>
+
+<p>Header file CXX_Objects.h requires adding file Src/cxxsupport.cxx to
+your module sources. CXX_Objects provides a set of wrapper classes that allow you access
+to most of the Python C API using a C++ notation that closely resembles Python. For
+example, this Python:</p>
+
+<pre>d = {}
+d["a"] = 1
+d["b"] = 2
+alist = d.keys()
+print alist</pre>
+
+<p>Can be written in C++:</p>
+
+<pre>Dict d;
+List alist;
+d["a"] = Int(1);
+d["b"] = Int(2);
+alist = d.keys();
+std::cout &lt;&lt; alist &lt;&lt; std::endl;
+</pre>
+
+<p>You can optionally use the CXX/Extensions.hxx facility described later
+to define Python extension modules and extension objects.</p>
+
+<h3>We avoid programming with Python object pointers</h3>
+
+<p>The essential idea is that we avoid, as much as possible, programming with pointers to
+Python objects, that is, variables of type <cite>PyObject*</cite>. Instead,
+we use instances of a family of C++ classes that represent the
+usual Python objects. This family is easily extendible to include new kinds of Python
+objects.</p>
+
+<p>For example, consider the case in which we wish to write a method, taking a single
+integer argument, that will create a Python <cite>dict</cite>
+ and insert into it that the integer plus one under the key <cite>value</cite>.
+ In C we might do that as follows:</p>
+
+<pre>static PyObject* mymodule_addvalue (PyObject* self, PyObject* args)
+ {
+ PyObject *d;
+ PyObject* f;
+ int k;
+ PyArgs_ParseTuple(args, &quot;i&quot;, &amp;k);
+ d = PyDict_New();
+ if (!d)
+ return NULL;
+
+ f = PyInt_NEW(k+1);
+ if(!f)
+ {
+ Py_DECREF(d); /* have to get rid of d first */
+ return NULL;
+ }
+ if(PyDict_SetItemString(d, &quot;value&quot;, f) == -1)
+ {
+ Py_DECREF(f);
+ Py_DECREF(d);
+ return NULL;
+ }
+
+ return d;
+ }</pre>
+
+<p>If you have written a significant Python extension, this tedium looks all too familiar.
+The vast bulk of the coding is error checking and cleanup. Now compare the same thing
+written in C++ using CXX/Objects.hxx. The things with Python-like names (Int, Dict, Tuple) are
+from CXX/Objects.hxx.</p>
+
+<pre>static PyObject* mymodule_addvalue (PyObject* self, PyObject* pargs)
+ {
+ try {
+ Tuple args(pargs);
+ args.verify_length(1);
+
+ Dict d;
+ Int k = args[0];
+ d[&quot;value&quot;] = k + 1;
+
+ return new_reference_to(d);
+ }
+ catch (const PyException&amp;)
+ {
+ return NULL;
+ }
+ }</pre>
+
+<p>If there are not the right number of arguments or the argument is not an
+integer, an exception is thrown. In this case we choose to catch it and convert it into a
+Python exception. The C++ exception handling mechanism takes care all the cleanup.</p>
+
+<p>Note that the creation of the <cite>Int k</cite> got the first argument <em>and</em> verified
+that it is an <cite>Int</cite>.</p>
+
+<p>Just to peek ahead, if you wrote this method in an
+ExtensionModule-derived module of your own, it would be a method and it could be written
+even more simply:</p>
+
+<pre>
+Object addvalue (Object &amp; self, const Tuple &amp; args)
+ {
+ args.verify_length(1);
+ Dict d;
+ Int k = args[0];
+ d["value"] = k + 1;
+ return d;
+ }
+</pre>
+
+<h2>The basic concept is to wrap Python pointers</h2>
+
+
+<p>The basic concept of CXX/Objects.hxx is to create a wrapper around
+each <cite>PyObject *</cite> so that the reference counting can be
+done automatically, thus eliminating the most frequent source of errors. In addition, we
+can then add methods and operators so that Python objects can be manipulated in C++
+much like you would in Python.</p>
+
+<p>Each <cite>Object</cite> contains a <cite>PyObject *</cite>
+to which it owns a reference. When an <cite>Object</cite> is destroyed, it releases its ownership on
+the pointer. Since C++ calls the destructors on objects that are about to go out of scope,
+we are guaranteed that we will keep the reference counts right even if we unexpectedly
+leave a routine with an exception.</p>
+
+<p>As a matter of philosophy, CXX/Objects.hxx prevents the creation of instances of its
+classes unless the instance will be a valid instance of its class. When an attempt is made
+to create an object that will not be valid, an exception is thrown.</p>
+
+<p>Class <cite>Object</cite> represents the most general kind of Python object. The rest of the classes
+that represent Python objects inherit from it.</p>
+
+<pre>Object
+ Type
+ Int
+ Float
+ Long
+ Complex
+ Char
+ Sequence -&gt; SeqBase&lt;T&gt;
+ String
+ Tuple
+ List
+ Mapping -&gt; MapBase&lt;T&gt;
+ Dict
+ Callable
+ Module</pre>
+
+<p>There are several constructors for each of these classes. For example, you can create
+an <cite>Int</cite> from an integer as in</p>
+
+<pre>Int s(3)</pre>
+
+<p>However, you can also create an instance of one of these classes using any <cite>PyObject*</cite> or
+another <cite>Object</cite>. If the corresponding Python object does not actually have the type
+desired, an exception is thrown. This is accomplished as follows. Class <cite>Object</cite> defines a
+virtual function <cite>accepts</cite>:</p>
+
+<pre>virtual bool accepts(PyObject* p)</pre>
+
+<p>The base class version of <cite>accepts</cite> returns true for any pointer p except 0. This means
+we can create an Object using any <cite>PyObject *</cite>, or from any other
+<cite>Object</cite>. However, if we attempt to create an <cite>Int</cite> from a <cite>PyObject *</cite>,
+the overridding version
+of <cite>accepts</cite> in class <cite>Int</cite> will only accept pointers that correspond to Python ints.
+Therefore if we have a <cite>Tuple t</cite> and we wish to get the first element and be sure it is an
+<cite>Int</cite>, we do</p>
+
+<pre>Int first_element = t[0]</pre>
+
+<p>This will not only accomplish the goal of extracting the first element of the <cite>Tuple t</cite>,
+but it will ensure that the result is an <cite>Int</cite>. If not, an exception is thrown. The
+exception mechanism is discussed later.</p>
+
+<h2>Class Object</h2>
+
+<p>Class <cite>Object</cite> serves as the base class for the other classes. Its default constructor
+constructs a <cite>Py_None</cite>, the unique object of Python type <cite>None</cite>. The interface to <cite>Object</cite>
+consists of a large number of methods corresponding to the operations that are defined for
+every Python object. In each case, the methods throw an exception if anything goes
+wrong.</p>
+
+<p>There is no method corresponding to <cite>PyObject_SetItem</cite> with an arbitrary Python object
+as a key. Instead, create an instance of a more specific child of <cite>Object</cite> and use the
+appropriate facilities.</p>
+
+<p>The comparison operators use the Python comparison function to compare values. The
+method <cite>is</cite> is available to test for absolute identity.</p>
+
+<p>A conversion to standard library string type <cite>std::string</cite> is supplied using method
+<cite>as_string</cite>. Stream output of PyCXX <cite>Object</cite> instances uses this conversion,
+which in turn uses the Python object's str() representation.</p>
+
+<p>All the numeric operators are defined on all possible combinations of <cite>Object</cite>,
+<cite>long</cite>, and <cite>double</cite>. These use the corresponding Python operators,
+and should the operation fail for some reason, an exception is thrown.</p>
+
+<h3>Dealing with pointers returned by the Python C API</h3>
+
+<p>Often, <cite>PyObject *</cite> pointers are acquired from some function,
+particularly functions in the Python C API. If you wish to make an object from the pointer
+returned by such a function, you need to know if the function returns you an <i>owned</i>
+or <i>unowned</i> reference. Unowned references are unusual but there are some cases where
+unowned references are returned.</p>
+
+<p>Usually, <cite>Object</cite> and its children acquire a new reference when constructed from a
+<cite>PyObject *</cite>. This is usually not the right behavior if the reference comes from one
+of the Python C API calls.</p>
+
+<p>If p is an owned reference, you can add the boolean <cite>true</cite> as an extra
+argument in the creation routine, <cite>Object(p, true)</cite>, or use the function <cite>asObject(p)</cite> which
+returns an <cite>Object</cite> created using the owned reference. For example, the routine
+<cite>PyString_FromString</cite> returns an owned reference to a Python string object. You could write:</p>
+
+<pre>Object w = asObject( PyString_FromString("my string") );</pre>
+
+<p>or using the constructor,</p>
+
+<pre>Object w( PyString_FromString("my string"), true );</pre>
+
+<p>In fact, you would never do this, since PyCXX has a class String and you can just say: </p>
+
+<pre>String w( "my string" );</pre>
+
+<p>Indeed, since most of the Python C API is similarly embodied in <cite>Object</cite>
+and its descendents, you probably will not use asObject all that often.</p>
+<h3>Table 1: Class Object</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Returns</th>
+ <th>Name(signature)</th>
+ <th>Comment</th>
+ </tr>
+ <tr>
+ <td colspan="3"><p align="center"><strong>Basic Methods</strong></td>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>Object (PyObject* pyob=Py_None, bool owned=false) </td>
+ <td>Construct from pointer. </td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Object (const Object&amp; ob)</td>
+ <td>Copycons; acquires an owned reference.</td>
+ </tr>
+ <tr>
+ <td class=code>Object&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs) </td>
+ <td>Acquires an owned reference.</td>
+ </tr>
+ <tr>
+ <td class=code>Object&amp;</td>
+ <td class=code>operator= (PyObject* rhsp) </td>
+ <td>Acquires an owned reference.</td>
+ </tr>
+ <tr>
+ <td class=code>virtual</td>
+ <td class=code>~Object () </td>
+ <td>Releases the reference.</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>increment_reference_count() </td>
+ <td>Explicitly increment the count</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>decrement_reference_count()</td>
+ <td>Explicitly decrement count but not to zero</td>
+ </tr>
+ <tr>
+ <td class=code>PyObject*</td>
+ <td class=code>operator* () const</td>
+ <td>Lends the pointer</td>
+ </tr>
+ <tr>
+ <td class=code>PyObject*</td>
+ <td class=code>ptr () const</td>
+ <td>Lends the pointer</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool</td>
+ <td class=code>accepts (PyObject *pyob) const</td>
+ <td>Would assignment of pyob to this object succeed?</td>
+ </tr>
+ <tr>
+ <td class=code>std::string</td>
+ <td class=code>as_string() const</td>
+ <td>str() representation</td>
+ </tr>
+ <tr>
+ <td colspan="3" align="center"><strong>Python API Interface</strong></td>
+ </tr>
+ <tr>
+ <td class=code>int</td>
+ <td class=code>reference_count () const </td>
+ <td>reference count</td>
+ </tr>
+ <tr>
+ <td class=code>Type</td>
+ <td class=code>type () const</td>
+ <td>associated type object</td>
+ </tr>
+ <tr>
+ <td class=code>String</td>
+ <td class=code>str () const</td>
+ <td>str() representation</td>
+ </tr>
+ <tr>
+ <td class=code>String</td>
+ <td class=code>repr () const</td>
+ <td>repr () representation</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>hasAttr (const std::string&amp; s) const</td>
+ <td>hasattr(this, s)</td>
+ </tr>
+ <tr>
+ <td class=code>Object</td>
+ <td class=code>getAttr (const std::string&amp; s) const</td>
+ <td>getattr(this, s)</td>
+ </tr>
+ <tr>
+ <td class=code>Object</td>
+ <td class=code>getItem (const Object&amp; key) const</td>
+ <td>getitem(this, key)</td>
+ </tr>
+ <tr>
+ <td class=code>long</td>
+ <td class=code>hashValue () const</td>
+ <td>hash(this)</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>setAttr (const std::string&amp; s,<br>const Object&amp; value)</td>
+ <td>this.s = value</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>delAttr (const std::string&amp; s) </td>
+ <td>del this.s</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>delItem (const Object&amp; key) </td>
+ <td>del this[key]</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isCallable () const</td>
+ <td>does this have callable behavior?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isList () const</td>
+ <td>is this a Python list?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isMapping () const</td>
+ <td>does this have mapping behaviors?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isNumeric () const</td>
+ <td>does this have numeric behaviors?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isSequence () const </td>
+ <td>does this have sequence behaviors?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isTrue () const</td>
+ <td>is this true in the Python sense?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isType (const Type&amp; t) const</td>
+ <td>is type(this) == t?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isTuple() const</td>
+ <td>is this a Python tuple?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isString() const</td>
+ <td>is this a Python string?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isUnicode() const</td>
+ <td>is this a Python Unicode string?</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>isDict() const</td>
+ <td>is this a Python dictionary?</td>
+ </tr>
+ <tr>
+ <td colspan="3" align="center"><strong>Comparison Operators</strong></td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>is(PyObject* pother) const</td>
+ <td>test for identity</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>is(const Object&amp; other) const</td>
+ <td>test for identity</td>
+ </tr>
+ <tr>
+ <td class=code>bool </td>
+ <td class=code>operator==(const Object&amp; o2) const</td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>operator!=(const Object&amp; o2) const</td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>operator&gt;=(const Object&amp; o2) const</td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>operator&lt;=(const Object&amp; o2) const </td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>operator&lt;(const Object&amp; o2) const</td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+ <tr>
+ <td class=code>bool</td>
+ <td class=code>operator&gt;(const Object&amp; o2) const</td>
+ <td>Comparisons use Python cmp</td>
+ </tr>
+</table>
+
+<h1>The Basic Types</h1>
+
+<p>Corresponding to each of the basic Python types is a class that inherits from Object.
+Here are the interfaces for those types. Each of them inherits from Object and therefore
+has all of the inherited methods listed for Object. Where a virtual function is overridden
+in a class, the name is underlined. </p>
+
+<h2>Class Type</h2>
+
+<p>Class Type corresponds to Python type objects. There is no default constructor.</p>
+
+<h3>Table 2: class Type</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Returns</th>
+ <th>Name and Signature</th>
+ <th>Comments</th>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Type (PyObject* pyob, bool owned = false)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Type (const Object&amp; ob)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Type(const Type&amp; t)</td>
+ <td>Copycons</td>
+ </tr>
+ <tr>
+ <td class=code>Type&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs) </td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>Type&amp;</td>
+ <td class=code>operator= (PyObject* rhsp) </td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool</td>
+ <td class=code><u>accepts</u> (PyObject *pyob) const</td>
+ <td>Uses PyType_Check</td>
+ </tr>
+</table>
+
+<h2>Class Int</h2>
+
+<p>Class Int, derived publically from Object, corresponds to Python ints. Note that the
+latter correspond to C long ints. Class Int has an implicit user-defined conversion to
+long int. All constructors, on the other hand, are explicit. The default constructor
+creates a Python int zero.</p>
+
+<h3>Table 3: class Int</h3>
+
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Returns</td>
+ <th>Name and Signature</td>
+ <th>Comments</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Int (PyObject *pyob, bool owned= false, bool owned = false)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Int (const Int&amp; ob)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Int (long v = 0L)</td>
+ <td>Construct from long</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Int (int v)</td>
+ <td>Contruct from int</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Int (const Object&amp; ob)</td>
+ <td>Copycons</td>
+ </tr>
+ <tr>
+ <td class=code>Int&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>Int&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool&nbsp;&nbsp; </td>
+ <td class=code> (PyObject *pyob) const </td>
+ <td>Based on PyInt_Check</td>
+ </tr>
+ <tr>
+ <td class=code>long</td>
+ <td class=code>operator long() const </td>
+ <td><em>Implicit</em> conversion to long int</td>
+ </tr>
+ <tr>
+ <td class=code>Int&amp;</td>
+ <td class=code>operator= (int v)</td>
+ <td>Assign from int</td>
+ </tr>
+ <tr>
+ <td class=code>Int&amp;</td>
+ <td class=code>operator= (long v) </td>
+ <td>Assign from long</td>
+ </tr>
+</table>
+
+<hr>
+
+<h2>Class Long</h2>
+
+<p>Class Long, derived publically from Object, corresponds to Python type long. In Python,
+a long is an integer type of unlimited size, and is usually used for applications such as
+cryptography, not as a normal integer. Implicit conversions to both double and long are
+provided, although the latter may of course fail if the number is actually too big. All
+constructors are explicit. The default constructor produces a Python long zero.</p>
+
+<h3>Table 4: Class Long</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Returns</td>
+ <th>Name and Signature</td>
+ <th>Comments</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Long (PyObject *pyob</a>, bool owned = false)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Long (const Int&amp; ob)</td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Long (long v = 0L)</td>
+ <td>Construct from long</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Long (int v)</td>
+ <td>Contruct from int</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Long (const Object&amp; ob)</td>
+ <td>Copycons</td>
+ </tr>
+ <tr>
+ <td class=code>Long&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>Long&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool</td>
+ <td class=code>(PyObject *pyob) const </td>
+ <td>Based on PyLong_Check</td>
+ </tr>
+ <tr>
+ <td class=code>double</td>
+ <td class=code>operator double() const </td>
+ <td><em>Implicit</em> conversion to double</td>
+ </tr>
+ <tr>
+ <td class=code>long</td>
+ <td class=code>operator long() const</td>
+ <td><em>Implicit</em> conversion to long</td>
+ </tr>
+ <tr>
+ <td class=code>Long&amp;</td>
+ <td class=code>operator= (int v)</td>
+ <td>Assign from int</td>
+ </tr>
+ <tr>
+ <td class=code>Long&amp;</td>
+ <td class=code>operator= (long v) </td>
+ <td>Assign from long</td>
+ </tr>
+</table>
+
+<h2>Class Float</h2>
+
+<p>Class Float corresponds to Python floats, which in turn correspond to C double. The
+default constructor produces the Python float 0.0. </p>
+
+<h3>Table 5: Class Float</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Returns</td>
+ <th>Name and Signature</td>
+ <th>Comments</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Float (PyObject *pyob</a>, bool owned = false)
+ </td>
+ <td>Constructor</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Float (const Float&amp; f)&nbsp;&nbsp; </td>
+ <td>Construct from float</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Float (double v=0.0)</td>
+ <td>Construct from double</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Float (const Object&amp; ob)</td>
+ <td>Copycons</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool </td>
+ <td class=code>accepts (PyObject *pyob) const</td>
+ <td>Based on PyFloat_Check</td>
+ </tr>
+ <tr>
+ <td class=code>double </td>
+ <td class=code>operator double () const</td>
+ <td><em>Implicit</em> conversion to double</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp; </td>
+ <td class=code>operator= (double v)</td>
+ <td>Assign from double</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp; </td>
+ <td class=code>operator= (int v)</td>
+ <td>Assign from int</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp; </td>
+ <td class=code>operator= (long v)</td>
+ <td>Assign from long</td>
+ </tr>
+ <tr>
+ <td class=code>Float&amp; </td>
+ <td class=code>operator= (const Int&amp; iob)</td>
+ <td>Assign from Int</td>
+ </tr>
+</table>
+
+<h1>Sequences</h1>
+
+<p>PyCXX implements a quite sophisticated wrapper class for Python sequences. While every
+effort has been made to disguise the sophistication, it may pop up in the form of obscure
+compiler error messages, so in this documentation we will first detail normal usage and
+then discuss what is under the hood.</p>
+
+<p>The basic idea is that we would like the subscript operator [] to work properly, and to
+be able to use STL-style iterators and STL algorithms across the elements of the sequence.</p>
+
+<p>Sequences are implemented in terms of a templated base class, SeqBase&lt;T&gt;. The
+parameter T is the answer to the question, sequence of what? For Lists, for example, T is
+Object, because the most specific thing we know about an element of a List is simply that
+it is an Object. (Class List is defined below; it is a descendent of Object that holds a
+pointer to a Python list). For strings, T is Char, which is a wrapper in turn of Python
+strings whose length is one.</p>
+
+<p>For convenience, the word <strong>Sequence</strong> is a typedef of SeqBase&lt;Object&gt;.</p>
+
+<h2>General sequences</h2>
+
+<p>Suppose you are writing an extension module method that expects the first argument to
+be any kind of Python sequence, and you wish to return the length of that sequence. You
+might write:</p>
+
+<pre>static PyObject*
+my_module_seqlen (PyObject *self, PyObject* args) {
+ try
+ {
+ Tuple t(args); // set up a Tuple pointing to the arguments.
+ if(t.length() != 1)
+ throw PyException(&quot;Incorrect number of arguments to seqlen.&quot;);
+ Sequence s = t[0]; // get argument and be sure it is a sequence
+ return new_reference_to(Int(s.length()));
+ }
+ catch(const PyException&amp;)
+ {
+ return Py_Null;
+ }
+}</pre>
+
+<p>As we will explain later, the try/catch structure converts any errors, such as the
+first argument not being a sequence, into a Python exception.</p>
+
+<h3>Subscripting</h3>
+
+<p>When a sequence is subscripted, the value returned is a special kind of object which
+serves as a proxy object. The general idea of proxy objects is discussed in Scott Meyers'
+book, &quot;More Effective C++&quot;. Proxy objects are necessary because when one
+subscripts a sequence it is not clear whether the value is to be used or the location
+assigned to. Our proxy object is even more complicated than normal because a sequence
+reference such as s[i] is not a direct reference to the i'th object of s. </p>
+
+<p>In normal use, you are not supposed to notice this magic going on behind your back. You
+write:</p>
+
+<pre>Object t;
+Sequence s;
+s[2] = t + s[1]</pre>
+
+<p>and here is what happens: s[1] returns a proxy object. Since there is no addition
+operator in Object that takes a proxy as an argument, the compiler decides to invoke an
+automatic conversion of the proxy to an Object, which returns the desired component of s.
+The addition takes place, and then there is an assignment operator in the proxy class
+created by the s[2], and that assignment operator stuffs the result into the 2 component
+of s.</p>
+
+<p>It is possible to fool this mechanism and end up with a compiler failing to admit that
+a s[i] is an Object. If that happens, you can work around it by writing Object(s[i]),
+which makes the desired implicit conversion, explicit.</p>
+
+<h3>Iterators</h3>
+
+<p>Each sequence class provides the following interface. The class seqref&lt;T&gt; is the
+proxy class. We omit the details of the iterator, const_iterator, and seqref&lt;T&gt;
+here. See CXX_Objects.h if necessary. The purpose of most of this interface is to satisfy
+requirements of the STL.</p>
+
+<h3>The SeqBase&lt;T&gt; Interface</h3>
+
+<p>SeqBase&lt;T&gt; inherits from Object.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ </tr>
+ <tr>
+ <td class=code>typedef int </td>
+ <td class=code>size_type</td>
+ </tr>
+ <tr>
+ <td class=code>typedef seqref&lt;T&gt;</td>
+ <td class=code>reference</td>
+ </tr>
+ <tr>
+ <td class=code>typedef T </td>
+ <td class=code>const_reference</td>
+ </tr>
+ <tr>
+ <td class=code>typedef seqref&lt;T&gt;*</td>
+ <td class=code>pointer</td>
+ </tr>
+ <tr>
+ <td class=code>typedef int </td>
+ <td class=code>difference_type</td>
+ </tr>
+ <tr>
+ <td class=code>virtual size_type</td>
+ <td class=code>max_size() const</td>
+ </tr>
+ <tr>
+ <td class=code>virtual size_type </td>
+ <td class=code>capacity() const;</td>
+ </tr>
+ <tr>
+ <td class=code>virtual void </td>
+ <td class=code>swap(SeqBase&lt;T&gt;&amp; c);</td>
+ </tr>
+ <tr>
+ <td class=code>virtual size_type </td>
+ <td class=code>size () const;</td>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>SeqBase&lt;T&gt; ();</td>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>SeqBase&lt;T&gt; (PyObject* pyob, bool owned = false);</td>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>SeqBase&lt;T&gt; (const Object&amp; ob);</td>
+ </tr>
+ <tr>
+ <td class=code>SeqBase&lt;T&gt;&amp; </td>
+ <td class=code>operator= (const Object&amp; rhs);</td>
+ </tr>
+ <tr>
+ <td class=code>SeqBase&lt;T&gt;&amp; </td>
+ <td class=code>operator= (PyObject* rhsp);</td>
+ </tr>
+ <tr>
+ <td class=code>virtual bool </td>
+ <td class=code>accepts (PyObject *pyob) const;</td>
+ </tr>
+ <tr>
+ <td class=code>size_type </td>
+ <td class=code>length () const ;</td>
+ </tr>
+ <tr>
+ <td class=code>const T </td>
+ <td class=code>operator[](size_type index) const; </td>
+ </tr>
+ <tr>
+ <td class=code>seqref&lt;T&gt; </td>
+ <td class=code>operator[](size_type index); </td>
+ </tr>
+ <tr>
+ <td class=code>virtual T </td>
+ <td class=code>getItem (size_type i) const;</td>
+ </tr>
+ <tr>
+ <td class=code>virtual void </td>
+ <td class=code>setItem (size_type i, const T&amp; ob);</td>
+ </tr>
+ <tr>
+ <td class=code>SeqBase&lt;T&gt; </td>
+ <td class=code>repeat (int count) const;</td>
+ </tr>
+ <tr>
+ <td class=code>SeqBase&lt;T&gt; </td>
+ <td class=code>concat (const SeqBase&lt;T&gt;&amp; other) const ;</td>
+ </tr>
+ <tr>
+ <td class=code>const T </td>
+ <td class=code>front () const;</td>
+ </tr>
+ <tr>
+ <td class=code>seqref&lt;T&gt; </td>
+ <td class=code>front();</td>
+ </tr>
+ <tr>
+ <td class=code>const T </td>
+ <td class=code>back () const;</td>
+ </tr>
+ <tr>
+ <td class=code>seqref&lt;T&gt; </td>
+ <td class=code>back(); </td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>verify_length(size_type required_size);</td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>verify_length(size_type min_size, size_type max_size);</td>
+ </tr>
+ <tr>
+ <td class=code>class</td>
+ <td class=code>iterator;</td>
+ </tr>
+ <tr>
+ <td class=code>iterator </td>
+ <td class=code>begin (); </td>
+ </tr>
+ <tr>
+ <td class=code>iterator </td>
+ <td class=code>end ();</td>
+ </tr>
+ <tr>
+ <td class=code>class </td>
+ <td class=code>const_iterator;</td>
+ </tr>
+ <tr>
+ <td class=code>const_iterator </td>
+ <td class=code>begin () const;</td>
+ </tr>
+ <tr>
+ <td class=code>const_iterator </td>
+ <td class=code>end () const;</td>
+ </tr>
+</table>
+
+<p>Any heir of class Object that has a sequence behavior should inherit from class
+SeqBase&lt;T&gt;, where T is specified as the type of object that represents the
+individual elements of the sequence. The requirements on T are that it has a constructor
+that takes a PyObject* as an argument, that it has a default constructor, a copy
+constructor, and an assignment operator. In short, any properly defined heir of Object
+will work. </p>
+
+<h2>Classes Char and String</h2>
+
+<p>Python strings are unusual in that they are immutable sequences of characters. However,
+there is no character type per se; rather, when subscripted strings return a string of
+length one. To simulate this, we define two classes Char and String. The Char class
+represents a Python string object of length one. The String class represents a Python
+string, and its elements make up a sequence of Char's.</p>
+
+<p>The user interface for Char is limited. Unlike String, for example, it is not a
+sequence.</p>
+
+<h3>The Char interface</h3>
+
+<p>Char inherits from Object.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Char (PyObject *pyob, bool owned = false)</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Char (const Object&amp; ob) </td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Char (const std::string&amp; v = &quot;&quot;) </td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Char (char v)</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Char (Py_UNICODE v)</td>
+ </tr>
+ <tr>
+ <td class=code>Char&amp;</td>
+ <td class=code>operator= (const std::string&amp; v)</td>
+ </tr>
+ <tr>
+ <td class=code>Char&amp;</td>
+ <td class=code>operator= (char v) </td>
+ </tr>
+ <tr>
+ <td class=code>Char&amp;</td>
+ <td class=code>operator= (Py_UNICODE v) </td>
+ </tr>
+ <tr>
+ <td class=code>Char&amp;</td>
+ <td class=code>operator= (std::basic_string<Py_UNICODE> v) </td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>operator String() const</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>operator std::string () const </td>
+ </tr>
+</table>
+
+<h3>The String Interface</h3>
+
+<p>String inherits from SeqBase&lt;Char&gt;.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>String (PyObject *pyob, bool owned = false)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const Object&amp; ob)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const std::string&amp; v = &quot;&quot;)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const std::string&amp; v, const char *encoding, const char *error=&quot;strict&quot;)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const char *s, const char *encoding, const char *error=&quot;strict&quot;)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const char *s, int len, const char *encoding, const char *error=&quot;strict&quot;)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const std::string&amp; v, std::string::size_type vsize)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>String (const char* v)</td>
+ </tr>
+ <tr>
+ <td class=code>String&amp;</td>
+ <td class=code>operator= (const std::string&amp; v) </td>
+ </tr>
+ <tr>
+ <td class=code>std::string</td>
+ <td class=code>operator std::string () const</td>
+ </tr>
+ <tr>
+ <td class=code>String</td>
+ <td class=code>encode( const char *encoding, const char *error=&quot;strict&quot; )</td>
+ </tr>
+ <tr>
+ <td class=code>String</td>
+ <td class=code>decode( const char *encoding, const char *error=&quot;strict&quot; )</td>
+ </tr>
+ <tr>
+ <td class=code>std::string</td>
+ <td class=code>as_std_string() const</td>
+ </tr>
+ <tr>
+ <td class=code>unicodestring</td>
+ <td class=code>as_unicodestring() const</td>
+ </tr>
+</table>
+
+<h2>Class Tuple</h2>
+
+<p>Class Tuple represents Python tuples. A Tuple is a Sequence. There are two kinds of
+constructors: one takes a PyObject* as usual, the other takes an integer number as an
+argument and returns a Tuple of that length, each component initialized to Py_None. The
+default constructor produces an empty Tuple. </p>
+
+<p>Tuples are not immutable, but attempts to assign to their components will fail if the
+reference count is not 1. That is, it is safe to set the elements of a Tuple you have just
+made, but not thereafter.</p>
+
+<p>Example: create a Tuple containing (1, 2, 4)</p>
+
+<pre>Tuple t(3)
+t[0] = Int(1)
+t[1] = Int(2)
+t[2] = Int(4)</pre>
+
+<p>Example: create a Tuple from a list:</p>
+
+<pre>Dict d
+...
+Tuple t(d.keys())</pre>
+
+<h3>The Tuple Interface</h3>
+
+<p>Tuple inherits from Sequence.. Special run-time checks prevent modification if the
+reference count is greater than one.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual void</td>
+ <td class=code>setItem (int offset, const Object&amp;ob) </td>
+ <td>setItem is overriden to handle tuples properly. </td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Tuple (PyObject *pyob, bool owned = false)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>Tuple (const Object&amp; ob)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Tuple (int size = 0)</td>
+ <td>Create a tuple of the given size. Items initialize to Py_None. Default is an empty
+ tuple.</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Tuple (const Sequence&amp; s)</td>
+ <td>Create a tuple from any sequence.</td>
+ </tr>
+ <tr>
+ <td class=code>Tuple&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Tuple&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Tuple</td>
+ <td class=code>getSlice (int i, int j) const </td>
+ <td>Equivalent to python's t[i:j]</td>
+ </tr>
+</table>
+
+<h2>Class List</h2>
+
+<p>Class List represents a Python list, and the methods available faithfully reproduce the
+Python API for lists. A List is a Sequence.</p>
+
+<h3>The List Interface</h3>
+
+<p>List inherits from Sequence.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>List (PyObject *pyob, bool owned = false)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>List (const Object&amp; ob)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>List (int size = 0)</td>
+ <td>Create a list of the given size. Items initialized to Py_None. Default is an empty list.</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>List (const Sequence&amp; s)</td>
+ <td>Create a list from any sequence.</td>
+ </tr>
+ <tr>
+ <td class=code>List&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>List&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>List</td>
+ <td class=code>getSlice (int i, int j) const</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>setSlice (int i, int j, const Object&amp; v) </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>append (const Object&amp; ob)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>insert (int i, const Object&amp; ob)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>sort ()</td>
+ <td>Sorts the list in place, using Python's member function. You can also use
+ the STL sort function on any List instance.</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>reverse ()</td>
+ <td>Reverses the list in place, using Python's member function.</td>
+ </tr>
+</table>
+
+<h1>Mappings</h1>
+
+<p>A class MapBase&lt;T&gt; is used as the base class for Python objects with a mapping
+behavior. The key behavior of this class is the ability to set and use items by
+subscripting with strings. A proxy class mapref&lt;T&gt; is defined to produce the correct
+behavior for both use and assignment.</p>
+
+<p>For convenience, <cite>Mapping</cite> is a typedef for <cite>MapBase&lt;Object&gt;</cite>.</p>
+
+<h3>The MapBase&lt;T&gt; interface</h3>
+
+<p>MapBase&lt;T&gt; inherits from Object. T should be chosen to reflect the kind of
+element returned by the mapping.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>T</td>
+ <td class=code>operator[](const std::string&amp; key) const</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>mapref&lt;T&gt; </td>
+ <td class=code>operator[](const std::string&amp; key)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>int</td>
+ <td class=code>length () const</td>
+ <td>Number of entries.</td>
+ </tr>
+ <tr>
+ <td class=code>int</td>
+ <td class=code>hasKey (const std::string&amp; s) const </td>
+ <td>Is m[s] defined?</td>
+ </tr>
+ <tr>
+ <td class=code>T</td>
+ <td class=code>getItem (const std::string&amp; s) const</td>
+ <td>m[s]</td>
+ </tr>
+ <tr>
+ <td class=code>virtual void</td>
+ <td class=code>setItem (const std::string&amp; s, const Object&amp; ob)</td>
+ <td>m[s] = ob</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>delItem (const std::string&amp; s)</td>
+ <td>del m[s]</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>delItem (const Object&amp; s)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>List</td>
+ <td class=code>keys () const</td>
+ <td>A list of the keys.</td>
+ </tr>
+ <tr>
+ <td class=code>List</td>
+ <td class=code>values () const</td>
+ <td>A list of the values.</td>
+ </tr>
+ <tr>
+ <td class=code>List</td>
+ <td class=code>items () const</td>
+ <td>Each item is a key-value pair.</td>
+ </tr>
+</table>
+
+<h2>Class Dict</h2>
+
+<p>Class Dict represents Python dictionarys. A Dict is a Mapping. Assignment to
+subscripts can be used to set the components.</p>
+
+<pre>Dict d
+d[&quot;Paul Dubois&quot;] = &quot;(925)-422-5426&quot;</pre>
+
+<h3>Interface for Class Dict</h3>
+
+<p>Dict inherits from MapBase&lt;Object&gt;.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Dict (PyObject *pyob</a>, bool owned = false)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>Dict (const Dict&amp; ob)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>Dict () </td>
+ <td>Creates an empty dictionary</td>
+ </tr>
+ <tr>
+ <td class=code>Dict&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Dict&amp;</td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td></td>
+ </tr>
+</table>
+
+<h1>Other classes and facilities.</h1>
+
+<p>Class Callable provides an interface to those Python objects that support a call
+method. Class Module holds a pointer to a module. If you want to create an extension
+module, however, see the extension facility. There is a large set of numeric operators.</p>
+
+<h3>Interface to class Callable</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Callable (PyObject *pyob</a>, bool owned = false)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Callable&amp; </td>
+ <td class=code>operator= (const Object&amp; rhs)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Callable&amp; </td>
+ <td class=code>operator= (PyObject* rhsp)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>Object</td>
+ <td class=code>apply(const Tuple&amp; args) const</td>
+ <td>Call the object with the given arguments</td>
+ </tr>
+ <tr>
+ <td class=code>Object</td>
+ <td class=code>apply(PyObject* pargs = 0) const </td>
+ <td>Call the object with args as the arguments. Checks that pargs is a tuple.</td>
+ </tr>
+</table>
+
+<h3>Interface to class Module</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Module (PyObject* pyob, bool owned = false)</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>Module (const std::string name)</td>
+ <td>Construct from name of module; does the import if needed.</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td class=code>Module (const Module&amp; ob) </td>
+ <td>Copy constructor</td>
+ </tr>
+ <tr>
+ <td class=code>Module&amp;</td>
+ <td class=code>operator= (const Object&amp; rhs) </td>
+ <td>Assignment</td>
+ </tr>
+ <tr>
+ <td class=code>Module&amp;</td>
+ <td class=code>operator= (PyObject* rhsp) </td>
+ <td>Assignment</td>
+ </tr>
+</table>
+
+<h3>Numeric interface</h3>
+
+<p>Unary operators for plus and minus, and binary operators +, -, *, /, and % are defined
+for pairs of objects and for objects with scalar integers or doubles (in either
+order). Functions abs(ob) and coerce(o1, o2) are also defined. </p>
+
+<p>The signature for coerce is:</p>
+
+<pre>inline std::pair&lt;Object,Object&gt; coerce(const Object&amp; a, const Object&amp; b)</pre>
+
+<p>Unlike the C API function, this simply returns the pair after coercion.</p>
+
+<h3>Stream I/O</h3>
+
+<p>Any object can be printed using stream I/O, using std::ostream&amp; operator&lt;&lt;
+(std::ostream&amp; os, const Object&amp; ob). The object's str() representation is
+converted to a standard string which is passed to std::ostream&amp; operator&lt;&lt;
+(std::ostream&amp; os, const std::string&amp;).</p>
+
+<h2>Exceptions</h2>
+
+<p>The Python exception facility and the C++ exception facility can be merged via the use
+of try/catch blocks in the bodies of extension objects and module functions.</p>
+
+<h3>Class Exception and its children</h3>
+
+<p>A set of classes is provided. Each is derived from class Exception, and represents a
+particular sort of Python exception, such as IndexError, RuntimeError, ValueError. Each of
+them (other than Exception) has a constructor which takes an explanatory string as an
+argument, and is used in a throw statement such as:</p>
+
+<pre>throw IndexError(&quot;Index too large in MyObject access.&quot;);</pre>
+
+<p>If in using a routine from the Python API, you discover that it has returned a NULL
+indicating an error, then Python has already set the error message. In that case you
+merely throw Exception.</p>
+
+<h3>List of Exceptions</h3>
+
+<p>The exception hierarchy mirrors the Python exception hierarchy. The concrete exception
+classes are shown here.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</th>
+ <th>Interface for class Exception</th>
+ </tr>
+ <tr>
+ <td class=code>explicit </td>
+ <td class=code>Exception()</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>Exception (const std::string&amp; reason) </td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>Exception (PyObject* exception, const std::string&amp; reason) </td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>clear()</td>
+ </tr>
+ <tr>
+ <td class=code></td>
+ <td>Constructors for other children of class Exception</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>TypeError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>IndexError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>AttributeError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>NameError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>RuntimeError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>SystemError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>KeyError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>ValueError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>OverflowError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>ZeroDivisionError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>MemoryError (const std::string&amp; reason)</td>
+ </tr>
+ <tr>
+ <td class=code> </td>
+ <td class=code>SystemExit (const std::string&amp; reason)</td>
+ </tr>
+</table>
+
+<h2>Using Exceptions in extension methods</h2>
+
+<p>The exception facility allows you to integrate the C++ and Python exception mechanisms.
+To do this, you must use the style described below when writing module methods in the old
+C style. </p>
+
+<p>Note: If using the ExtensionModule or PythonExtension mechanisms described below, the
+method handlers include exception handling so that you only need to use exceptions
+explicitly in unusual cases.</p>
+
+<h3>Catching Exceptions from the Python API or PyCXX.</h3>
+
+<p>When writing an extension module method, you can use the following boilerplate. Any
+exceptions caused by the Python API or PyCXX itself will be converted into a Python
+exception. Note that Exception is the most general of the exceptions listed above, and
+therefore this one catch clause will serve to catch all of them. You may wish to catch
+other exceptions, not in the Exception family, in the same way. If so, you need to make
+sure you set the error in Python before returning.</p>
+
+<pre>static PyObject *
+some_module_method(PyObject* self, PyObject* args)
+{
+ Tuple a(args); // we know args is a Tuple
+ try {
+ ...calculate something from a...
+ return ...something, usually of the form new_reference_to(some Object);
+ }
+ catch(const Exception&amp;) {
+ //Exception caught, passing it on to Python
+ return Null ();
+ }
+}
+</pre>
+
+<h3>How to clear an Exception</h3>
+
+<p>If you anticipate that an Exception may be thrown and wish to recover from it, change
+the catch phrase to set a reference to an Exception, and use the method clear() from class
+Exception to clear it.:</p>
+
+<pre>catch(Exception&amp; e)
+ {
+ e.clear();
+ ...now decide what to do about it...
+ }
+</pre>
+
+<h2>Extension Facilities</h2>
+
+<p>CXX/Extensions.hxx provides facilities for:
+
+<ul>
+ <li>Creating a Python extension module</li>
+ <li>Creating new Python extension types</li>
+</ul>
+
+<p>These facilities use CXX/Objects.hxx and its support file cxxsupport.cxx.</p>
+
+<p>If you use CXX/Extensions.hxx you must also include source files cxxextensions.c and
+cxx_extensions.cxx</p>
+
+<h3>Creating an Python extension module</h3>
+
+<p>The usual method of creating a Python extension module is to declare and initialize its
+method table in C. This requires knowledge of the correct form for the table and the order
+in which entries are to be made into it, and requires casts to get everything to compile
+without warning. The PyCXX header file CXX/Extensions.h offers a simpler method. Here is a
+sample usage, in which a module named &quot;example&quot; is created. Note that two
+details are necessary:
+
+<ul>
+ <li>The initialization function must be declared to have external C linkage and to have the
+ expected name. This is a requirement imposed by Python</li>
+ <li>The ExtensionModule object must have a storage class that survives the call to the
+ initialization function. This is most easily accomplished by using a static local inside
+ the initialization function, as in initexample below.</li>
+</ul>
+
+<p>To create an extension module, you inherit from class ExtensionModule templated on
+yourself: In the constructor, you make calls to register methods of this class with Python
+as extension module methods. In this example, two methods are added (this is a simplified
+form of the example in Demo/example.cxx):</p>
+
+<pre>class example_module : public ExtensionModule&lt;example_module&gt;
+{
+public:
+ example_module()
+ : ExtensionModule&lt;example_module&gt;( &quot;example&quot; )
+ {
+ add_varargs_method(&quot;sum&quot;, &amp;example_module::ex_sum, &quot;sum(arglist) = sum of arguments&quot;);
+ add_varargs_method(&quot;test&quot;, &amp;example_module::ex_test, &quot;test(arglist) runs a test suite&quot;);
+
+ initialize( &quot;documentation for the example module&quot; );
+ }
+
+ virtual ~example_module() {}
+
+private:
+ Object ex_sum(const Tuple &amp;a) { ... }
+ Object ex_test(const Tuple &amp;a) { ... }
+};
+</pre>
+
+<p>To initialize the extension, you just instantiate one static instance (static so it
+does not destroy itself!):</p>
+
+<pre>void initexample()
+{
+static example_module* example = new example_module;
+}</pre>
+
+<p>The methods can be written to take Tuples as arguments and return Objects. If
+exceptions occur they are trapped for you and a Python exception is generated. So, for
+example, the implementation of ex_sum might be:</p>
+
+<pre>Object ex_sum (const Tuple &amp;a)
+ {
+ Float f(0.0);
+ for( int i = 0; i &lt; a.length(); i++ )
+ {
+ Float g(a[i]);
+ f = f + g;
+ }
+ return f;
+ }</pre>
+
+<p>class ExtensionModule contains methods to return itself as a Module object, or to
+return its dictionary.</p>
+
+<h3>Interface to class ExtensionModule</h3>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>explicit</td>
+ <td class=code>ExtensionModule (char* name) </td>
+ <td>Create an extension module named &quot;name&quot;</td>
+ </tr>
+ <tr>
+ <td class=code>virtual </td>
+ <td class=code>~ExtensionModule () </td>
+ <td>Destructor</td>
+ </tr>
+ <tr>
+ <td class=code>Dict</td>
+ <td class=code>moduleDictionary() const</td>
+ <td>Returns the module dictionary; module must be initialized.</td>
+ </tr>
+ <tr>
+ <td class=code>Module</td>
+ <td class=code>module() const</td>
+ <td>This module as a Module.</td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>add_varargs_method (char *name, method_varargs_function_t method, char *documentation=&quot;&quot;)</td>
+ <td>Add a method to the module.</td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>add_keyword_method (char *name, method_keyword_function_t method, char *documentation=&quot;&quot;</td>
+ <td>Add a method that takes keywords</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>initialize() (protected, call from constructor)</td>
+ <td>Initialize the module once all methods have been added. </td>
+ </tr>
+</table>
+
+<p>The signatures above are:</p>
+
+<pre>typedef Object (T::*method_varargs_function_t)( const Tuple &amp;args );
+typedef Object (T::*method_keyword_function_t)( const Tuple &amp;args, const Dict &amp;kws
+);</pre>
+
+<p>That is, the methods take a Tuple or a Tuple and a Dict, and return an Object. The
+example below has an &amp; in front of the name of the method; we found one compiler that
+needed this.</p>
+
+<h2>Creating a Python extension type</h2>
+
+<p>One of the great things about Python is the way you can create your own object types
+and have Python welcome them as first-class citizens. Unfortunately, part of the way you
+have to do this is not great. Key to the process is the creation of a Python &quot;type
+object&quot;. All instances of this type must share a reference to this one unique type
+object. The type object itself has a multitude of &quot;slots&quot; into which the
+addresses of functions can be added in order to give the object the desired behavior. </p>
+
+<p>Creating extension objects is of course harder since you must specify
+how the object behaves and give it methods. This is shown in some detail in the example
+range.h and range.cxx, with the test routine rangetest.cxx, in directory Demo. If you have never
+created a Python extension before, you should read the Extension manual first and be very
+familiar with Python's &quot;special class methods&quot;. Then what follows will make more
+sense.</p>
+
+<p>The basic idea is to inherit from PythonExtension templated on your self</p>
+
+<pre>class MyObject: public PythonExtension&lt;MyObject&gt; {...}</pre>
+
+<p>As a consequence:
+
+<ul>
+ <li>MyObject is a child of PyObject, so that a MyObject* is-a PyObject*. </li>
+ <li>A static method <cite>check(PyObject*)</cite> is created in class MyObject. This function
+ returns a boolean, testing whether or not the argument is in fact a pointer to an instance
+ of MyObject.</li>
+ <li>The user can connect methods of MyObject to Python so that they are methods on MyObject
+ objects. Each such method has the signature:<br>
+ Object method_name (const Tuple&amp; args).</li>
+ <li>The user can override virtual methods of PythonExtension in order to set behaviors.</li>
+ <li>A method is created to handle the deletion of an instance if and when its reference
+ count goes to zero. This method ensures the calling of the class destructor ~MyObject(),
+ if any, and releases the memory (see below).</li>
+ <li>Both automatic and heap-based instances of MyObject can be created.</li>
+</ul>
+
+<h3>Sample usage of PythonExtension</h3>
+
+<p>Here is a brief overview. You create a class that inherits from PythonExtension
+templated upon itself. You override various methods from PythonExtension to implement
+behaviors, such as getattr, sequence_item, etc. You can also add methods to the object
+that are usable from Python using a similar scheme as for module methods above. </p>
+
+<p>One of the consequences of inheriting from PythonExtension is that you are inheriting
+from PyObject itself. So your class is-a PyObject and instances of it can be passed to the
+Python C API. Note: this example uses the namespace feature of PyCXX.</p>
+
+<p>Hint: You can avoid needing to specify the Py:: prefix if you include the C++ statement
+<cite>using Py;</cite> at the top of your files.</p>
+
+<pre>class range: public Py::PythonExtension&lt;range&gt; {
+public:
+ ... constructors, data, etc.
+ ... methods not callable from Python
+ // initializer, see below
+ static void init_type();
+ // override functions from PythonExtension
+ virtual Py::Object repr();
+ virtual Py::Object getattr( const char *name );
+
+ virtual int sequence_length();
+ virtual Py::Object sequence_item( int i );
+ virtual Py::Object sequence_concat( const Py::Object &amp;j );
+ virtual Py::Object sequence_slice( int i, int j );
+
+ // define python methods of this object
+ Py::Object amethod (const Py::Tuple&amp; args);
+ Py::Object value (const Py::Tuple&amp; args);
+ Py::Object assign (const Py::Tuple&amp; args);
+};</pre>
+
+<p>
+To initialize the type we provide a static method that we can call from some module's
+initializer. We set the name, doc string, and indicate which behaviors range objects
+support. Then we adds the methods.</p>
+
+<pre>void range::init_type()
+{
+ behaviors().name(&quot;range&quot;);
+ behaviors().doc(&quot;range objects: start, stop, step&quot;);
+ behaviors().supportRepr();
+ behaviors().supportGetattr();
+ behaviors().supportSequenceType();
+
+ add_varargs_method(&quot;amethod&quot;, &amp;range::amethod,
+ &quot;demonstrate how to document amethod&quot;);
+ add_varargs_method(&quot;assign&quot;, &amp;range::assign);
+ add_varargs_method(&quot;value&quot;, &amp;range::value);
+}</pre>
+</a>
+
+<p>Do not forget to add the call range::init_type() to some module's init function. You will want
+a method in some module that can create range objects, too.</p>
+
+<h3>Interface to PythonExtension &lt;T&gt;</h3>
+
+<p>Your extension class T inherits PythonExtension&lt;T&gt;.</p>
+
+<table cellspacing=0 cellpadding=3px width="95%">
+ <tr>
+ <th>Type</td>
+ <th>Name</td>
+ <th>Comment</td>
+ </tr>
+ <tr>
+ <td class=code>virtual </td>
+ <td class=code>~PythonExtension&lt;T&gt;() </td>
+ <td>Destructor</td>
+ </tr>
+ <tr>
+ <td class=code>PyTypeObject* </td>
+ <td class=code>type_object() const</td>
+ <td>Returns the object type object.</td>
+ </tr>
+ <tr>
+ <td class=code>int</td>
+ <td class=code>check (PyObject* p)</td>
+ <td>Is p a T?</td>
+ </tr>
+ <tr>
+ <td colspan="3"><strong>Protected </strong></td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>add_varargs_method (char *name, method_keyword_function_t method, char *documentation=&quot;&quot;</td>
+ <td>Add a method that takes arguments</td>
+ </tr>
+ <tr>
+ <td class=code>void </td>
+ <td class=code>add_keyword_method (char *name, method_keyword_function_t method, char *documentation=&quot;&quot;</td>
+ <td>Add a method that takes keywords</td>
+ </tr>
+ <tr>
+ <td class=code>static PythonType&amp;</td>
+ <td class=code>behaviors()</td>
+ <td>The type object</td>
+ </tr>
+ <tr>
+ <td class=code>void</td>
+ <td class=code>initialize() (protected, call from constructor)</td>
+ <td>Initialize the module once all methods have been added. </td>
+ </tr>
+</table>
+
+<p>As before the signatures for the methods are Object mymethod(const Tuple&amp;
+args) and Object mykeywordmethod (const Tuple&amp; args, const Dict&amp; keys). In this
+case, the methods must be methods of T.</p>
+
+<p>To set the behaviors of the object you override some or all of these methods from
+PythonExtension&lt;T&gt;:</p>
+
+<pre> virtual int print( FILE *, int );
+ virtual Object getattr( const char * );
+ virtual int setattr( const char *, const Object &amp; );
+ virtual Object getattro( const Object &amp; );
+ virtual int setattro( const Object &amp;, const Object &amp; );
+ virtual int compare( const Object &amp; );
+ virtual Object repr();
+ virtual Object str();
+ virtual long hash();
+ virtual Object call( const Object &amp;, const Object &amp; );
+
+ // Sequence methods
+ virtual int sequence_length();
+ virtual Object sequence_concat( const Object &amp; );
+ virtual Object sequence_repeat( int );
+ virtual Object sequence_item( int );
+ virtual Object sequence_slice( int, int );
+ virtual int sequence_ass_item( int, const Object &amp; );
+ virtual int sequence_ass_slice( int, int, const Object &amp; );
+
+ // Mapping
+ virtual int mapping_length();
+ virtual Object mapping_subscript( const Object &amp; );
+ virtual int mapping_ass_subscript( const Object &amp;, const Object &amp; );
+
+ // Number
+ virtual int number_nonzero();
+ virtual Object number_negative();
+ virtual Object number_positive();
+ virtual Object number_absolute();
+ virtual Object number_invert();
+ virtual Object number_int();
+ virtual Object number_float();
+ virtual Object number_long();
+ virtual Object number_oct();
+ virtual Object number_hex();
+ virtual Object number_add( const Object &amp; );
+ virtual Object number_subtract( const Object &amp; );
+ virtual Object number_multiply( const Object &amp; );
+ virtual Object number_divide( const Object &amp; );
+ virtual Object number_remainder( const Object &amp; );
+ virtual Object number_divmod( const Object &amp; );
+ virtual Object number_lshift( const Object &amp; );
+ virtual Object number_rshift( const Object &amp; );
+ virtual Object number_and( const Object &amp; );
+ virtual Object number_xor( const Object &amp; );
+ virtual Object number_or( const Object &amp; );
+ virtual Object number_power( const Object &amp;, const Object &amp; );
+
+ // Buffer
+ virtual int buffer_getreadbuffer( int, void** );
+ virtual int buffer_getwritebuffer( int, void** );
+ virtual int buffer_getsegcount( int* );</pre>
+
+<p>Note that dealloc is not one of the functions you can override. That is what your
+destructor is for. As noted below, dealloc behavior is provided for you by
+PythonExtension.</p>
+
+<h3>Type initialization</h3>
+
+<p>To initialize your type, supply a static public member function that can be called
+from the extension module. In that function, obtain the PythonType object by calling
+behaviors() and apply appropriate &quot;support&quot; methods from PythonType to turn on
+the support for that behavior or set of behaviors.</p>
+
+<pre> void supportPrint(void);
+ void supportGetattr(void);
+ void supportSetattr(void);
+ void supportGetattro(void);
+ void supportSetattro(void);
+ void supportCompare(void);
+ void supportRepr(void);
+ void supportStr(void);
+ void supportHash(void);
+ void supportCall(void);
+
+ void supportSequenceType(void);
+ void supportMappingType(void);
+ void supportNumberType(void);
+ void supportBufferType(void);</pre>
+
+<p>Then call add_varargs_method or add_keyword_method to add any methods desired to the
+object.</p>
+
+<h3>Notes on memory management and extension objects</h3>
+
+<p>Normal Python objects exist only on the heap. That is unfortunate, as object creation
+and destruction can be relatively expensive. Class PythonExtension allows creation of both
+local and heap-based objects.</p>
+
+<p>If an extension object is created using operator new, as in:</p>
+
+<pre>range* my_r_ref = new range(1, 20, 3)</pre>
+
+<p>then the entity my_r_ref can be thought of as &quot;owning&quot; the reference created
+in the new object. Thus, the object will never have a reference count of zero. If the
+creator wishes to delete this object, they should either make sure the reference count is
+1 and then do delete my_r_ref, or decrement the reference with Py_DECREF(my_r_ref).</p>
+
+<p>Should my_r_ref give up ownership by being used in an Object constructor, all will
+still be well. When the Object goes out of scope its destructor will be called, and that
+will decrement the reference count, which in turn will trigger the special dealloc routine
+that calls the destructor and deletes the pointer.</p>
+
+<p>If the object is created with automatic scope, as in:</p>
+
+<pre>range my_r(1, 20, 3)</pre>
+
+<p>then my_r can be thought of as owning the reference, and when my_r goes out of scope
+the object will be destroyed. Of course, care must be taken not to have kept any permanent
+reference to this object. Fortunately, in the case of an exception, the C++ exception
+facility will call the destructor of my_r. Naturally, care must be taken not to end up
+with a dangling reference, but such objects can be created and destroyed more efficiently
+than heap-based PyObjects.</p>
+
+<h2>Putting it all together</h2>
+
+<p>The Demo directory of the distribution contains an extensive example of how to use many
+of the facilities in PyCXX. It also serves as a test routine. This test is not completely
+exhaustive but does excercise much of the facility.</p>
+
+<h2>Acknowledgment</h2>
+
+<p>Thank you to Geoffrey Furnish for patiently teaching me the finer points of C++ and its
+template facility, and his critique of PyCXX in particular. With version 4 I welcome Barry
+Scott as co-author. -- Paul Dubois</p>
+
+</body>
+</html>
diff --git a/lib/kross/python/cxx/README.html b/lib/kross/python/cxx/README.html
new file mode 100644
index 00000000..d698725a
--- /dev/null
+++ b/lib/kross/python/cxx/README.html
@@ -0,0 +1,436 @@
+<html>
+
+<head>
+<title>PyCXX README</title>
+
+<style>
+H1, H2, H3, H4 {color: #000099;
+ background-color: lightskyblue}
+h3 {position: relative; left: 20px}
+
+p {position: relative; left: 20px; margin-right: 20px}
+pre {color: #0000cc; background-color: #eeeeee; position: relative; left: 40px; margin-right: 80px;
+ border-style: solid; border-color: black; border-width: thin}
+kbd {color: #990000}
+p cite, ol cite, ul cite {font-family: monospace; font-style: normal; font-size: normal}
+li var, pre var, p var, kbd var {color: #009900; font-style: italic}
+li samp, pre samp, p samp, kbd samp {color: #009900; font-weight: bold}
+li p {position: relative; left: 0}
+table { position: relative; left: 20px; border: solid #888888 1px; background-color: #eeeeee}
+table th {border: solid #888888 1px; background-color: #88dd88; color: black}
+table td {border: solid #888888 1px}
+table td.code {border: solid #888888 1px;font-family: monospace; font-style: normal; font-size: normal}
+p.param {background-color: #eeeeee; border-top: lightskyblue solid 4}
+</style>
+</head>
+
+<body>
+
+<h1>PyCXX -- Python C++ Extensions Support</h1>
+
+<h2>Installation using distutils</h2>
+
+<h3>Windows Installation and Demo</h3>
+<ol>
+<li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx_5_3_1.tar.gz">
+http://prdownloads.sourceforge.net/cxx/pycxx_5_3_1.tar.gz</a>
+<li>Expand the archive into a directory of your choosing C:\ for example. Note: WinZip can expand .tar.gz files.
+<li>Install the PyCXX files:
+<ol>
+<li><pre>C:> cd \pycxx_5_3_1</pre>
+<li><pre>C:\pycxx_5_3_1> python setup.py install</pre>
+</ol>
+<li>Install the PyCXX Demo:
+<ol>
+<li><pre>C:> cd \PYCXX_5_3_1\Demo</pre>
+<li><pre>C:\PYCXX_5_3_1\Demo> python setup.py install</pre>
+</ol>
+<li>Run the demo:
+<ol>
+<li><pre>C:> python</pre>
+<li><pre>&gt;&gt;&gt; import CXX.example</pre>
+<li><pre>&gt;&gt;&gt; CXX.example.test()</pre>
+<li><pre>&gt;&gt;&gt; r = CXX.example.range( 11, 100, 13 )</pre>
+<li><pre>&gt;&gt;&gt; for i in r: print i</pre>
+<li><pre>...</pre>
+</ol>
+</ul>
+</ol>
+
+
+<h3>Unix Installation and Demo</h3>
+<p>Note: distutils is not available for Python 1.5.2</p>
+
+<ol>
+<li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/pycxx_5_3_1.tar.gz">
+http://prdownloads.sourceforge.net/cxx/PyCXX-V5.3.0.tar.gz</a>
+<li>Login as root. root access is typically needed on Unix systems to install the PyCXX files into the Python directories.
+<li>Expand the archive into a directory of your choosing ~\ for example.
+<li>Install the PyCXX files:
+<ol>
+<li><pre># cd ~\PYCXX_5_3_1</pre>
+<li><pre># python setup.py install</pre>
+</ol>
+<li>Install the PyCXX Demo:
+<ol>
+<li><pre># cd ~\PYCXX_5_3_1\Demo</pre>
+<li><pre># python setup.py install</pre>
+</ol>
+<li>Run the demo:
+<ol>
+<li><pre>~ python</pre>
+<li><pre>&gt;&gt;&gt; import CXX.example</pre>
+<li><pre>&gt;&gt;&gt; CXX.example.test()</pre>
+<li><pre>&gt;&gt;&gt; r = CXX.example.range( 11, 100, 13 )</pre>
+<li><pre>&gt;&gt;&gt; for i in r: print i</pre>
+<li><pre>...</pre>
+</ol>
+</ul>
+</ol>
+
+<h2>Installation using Project and Makefile</h2>
+
+<p>If you cannot or do not wish to use the distutils methods to work with PyCXX a set
+of Makefiles and Project files are provided.</p>
+
+<h3>Windows Installation and Demo</h3>
+<p>
+<ol>
+<li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/PyCXX-V5.3.0.tar.gz">
+http://prdownloads.sourceforge.net/cxx/pycxx_5_3_1.tar.gz</a>
+<li>Expand the archive into a directory of your choosing C:\ for example. WinZip can expand .tar.gz files.
+<li>Build the example. Using Microsoft Visual C++ 6.0 load the workspace corresponsing to the version of
+Python you wish the work with.
+<ul>
+<li>example_py15.dsw - Python 1.5.2
+<li>example_py20.dsw - Python 2.0 and 2.0.1
+<li>example_py21.dsw - Python 2.1 and 2.1.1
+<li>example_py22.dsw - Python 2.2 and its maintanence release
+<li>example_py23.dsw - Python 2.3 and its maintanence release
+</ul>
+<li>Run the example. (I'll assume you are testing Python 2.3)
+<ul>
+<li>cd c:\PYCXX_5_3_1\pyds23
+<li>c:\python21\python -c "import example;example.test()"
+</ul>
+</ol>
+</p>
+<h3>Unix Installation and Demo</h3>
+<p>
+<ol>
+<li>Fetch <a href="http://prdownloads.sourceforge.net/cxx/PyCXX-V5.3.0.tar.gz">
+http://prdownloads.sourceforge.net/cxx/PyCXX-V5.3.0.tar.gz</a>
+<li>Expand the archive into a directory of your choosing ~/ for example.
+<li>Select to makefile for your system and python version.
+<ul>
+<li>example_freebsd_py15.mak - FreeBSD Python 1.5.2 (see <a href="#note_1_5_2">note</a> below)
+<li>example_freebsd_py20.mak - FreeBSD Python 2.0, 2.0.1
+<li>example_freebsd_py21.mak - FreeBSD Python 2.1, 2.1.1
+<li>example_freebsd_py22.mak - FreeBSD Python 2.2
+<li>example_linux_py15.mak - Linux Python 1.5.2
+<li>example_linux_py20.mak - Linux Python 2.0, 2.0.1
+<li>example_linux_py21.mak - Linux Python 2.1, 2.1.1
+<li>example_linux_py22.mak - Linux Python 2.2
+</ul>
+<li>Build the example. Use GNU make<br>
+$ make -f <var>example-makefile</var> example.so
+<li>Run the example.<br>
+$ make -f <var>example-makefile</var> test
+</ol>
+</p>
+
+<p><a id="note_1_5_2">Note:</a> The Unix version of python 1.5.2 may need to be rebuilt so that C++ is support.
+If you get reports of undefined symbols like cout or cerr then its likely that python
+is not compiled and linked to support C and C++.</p>
+
+<p>To create a makefile for another vendors Unix follow these steps:</p>
+<ol>
+<li>copy one of the example make files above.
+<li>edit the variables to match your Python installation and C++ compile needs
+<li>Proceed to build and test as above.
+</ol>
+<p>Note: most of the makefile rules to build PyCXX and its example are contained in example_common.mak.
+</p>
+
+<h2>Revision History</h2>
+<h3>Version 5.3.1 (19-Jan-2005)</h3>
+<p>Support GCC4 and Microsoft .NET 2003 aka MSVC 7.1
+
+<h3>Version 5.3 (21-Oct-2004)</h3>
+<p>String object now support python string and unicode string objects.
+<p>Fix most bugs reported on SourceForge
+
+<h3>Version 5.2 (27-Nov-2003)</h3>
+<p>PyCXX supports Python version 2.3, 2.2, 2.1, 2.0 and 1.5.2 on Windows and Unix.</p>
+<p>Fixed problems with keyword functions.</p>
+<p>Improve Extension API to give access to names and docs
+<p>Support GCC 3.</p>
+<p>Added support for custom Exceptions</p>
+<p></p>
+
+<h3>Version 5.1 (2-Aug-2001)</h3>
+<p>I'm using the name PyCXX for this package, CXX is far to close to a compilers name.</p>
+
+<p>PyCXX supports Python version 2.2, 2.1.1, 2.1, 2.0, 2.0.1 and 1.5.2 on Windows and Unix.</p>
+
+<p>New in this release:</p>
+<ul>
+<li>Support for the Windows Linker /DELAYLOAD feature. Enable this feature by
+defining PY_WIN32_DELAYLOAD_PYTHON_DLL when compiling IndirectPythonInterface.cxx
+<li>Remove "CXX/Array.hxx" and associated code - its does not belong in PyCXX
+<li>Work on the docs. Mostly to clean up the HTML to allow more extensive work.
+<li>Reformated the sources to a consistent style. The mix of styles and tabs sizes
+was making working on the sources error prone.
+<li>Added workaround to setup.py to allow GCC to compile c++ code.
+<li>Added Microsoft Visual C++ 6.0 project files for 1.5, 2.0 and 2.1 builds
+<li>Added Unix make files for Linux (tested on RedHat 7.1) and FreeBSD (tested on 4.3)
+<li>Merged changes from Tom Malcolmson
+</ul>
+
+<h3>(July 9, 2000)</h3>
+<p>Renamed all header files to reflect the CXX include name space and that they are
+C++ header files.
+<p>
+<table cellspacing=0 cellpadding=3px>
+<tr><th>Old</th><th>New</th></tr>
+<tr><td>#include "CXX_Config.h"</td><td>#include "CXX/Config.hxx"</td>
+<tr><td>#include "CXX_Exception.h"</td><td>#include "CXX/Exception.hxx"</td>
+<tr><td>#include "CXX_Extensions.h"</td><td>#include "CXX/Extensions.hxx"</td>
+<tr><td>#include "CXX_Objects.h"</td><td>#include "CXX/Objects.hxx"</td>
+</table>
+
+<h3>Version 5 (May 18, 2000)</h3>
+<p>This version adds Distutils support for installation and some code cleanup.</p>
+
+<h3>Version 4 (October 11, 1999)</h3>
+
+<p>This version contains a massive revision to the part of CXX that supports creating
+extension objects and extension modules. Barry Scott contributed these changes.</p>
+
+<p>CXX has always consisted of two parts: the basic CXX_Objects.h and the more
+experimental CXX_Extensions.h. We will describe the changes to CXX_Objects first, and then
+the changes to CXX_Extensions.h.</p>
+
+<h3>Changes to CXX_Objects</h3>
+
+<h4>1. Owned option eliminates need for FromAPI in most cases</h4>
+
+<p>Object's constructor from PyObject* and method set have a new (backward compatible)
+signature:</p>
+
+<pre>
+Object (PyObject* pyob, bool owned = false);
+void set(PyObject* pyob, bool owned = false);
+</pre>
+
+<p>Users may call these with owned = true if they own the reference pyob already and want
+the Object instance to take over ownership.</p>
+
+<p>A new inline function Object asObject(PyObject* pyob) returns Object(pyob, true); thus,
+one way to construct an object from a pointer returned by the Python API is to call
+asObject on it. </p>
+
+<p>Previously a class FromAPI was provided to solve the problem of taking over an owned
+reference. FromAPI will be eliminated in the next release. It is no longer used by CXX
+itself or its demos. The new mechanism is much cleaner and more efficient.</p>
+
+<p>Other classes in CXX have been given the same &quot;owned&quot; option on their
+constructors: Int, Float, Long, Complex, SeqBase&lt;T&gt;, Tuple, List, Dict, Module,
+Callable.</p>
+
+<h4>2. Namespace support in compiler assumed</h4>
+
+<p>Since EGCS / GCC now supports namespaces and the standard library, the need for
+CXX_config.h is almost gone. We have eliminated all the macros except for one obscure one
+dealing with iterator traits in the standard library.</p>
+
+<h3>Changes to CXX_Extensions</h3>
+
+<p>The changes to CXX_Extensions.h are not backward compatible. However, they simplify
+coding so much that we think it is worth the disruption.</p>
+
+<h4>1. Creating an extension module</h4>
+
+<p>To create an extension module, you inherit from class ExtensionModule templated on
+yourself: In the constructor, you make calls to register methods of this class with Python
+as extension module methods. In this example, two methods are added (this is a simplified
+form of the example in Demo/example.cxx):</p>
+
+<pre>class example_module : public ExtensionModule&lt;example_module&gt;
+{
+public:
+ example_module()
+ : ExtensionModule&lt;example_module&gt;( &quot;example&quot; )
+ {
+ add_varargs_method(&quot;sum&quot;, &amp;example_module::ex_sum, &quot;sum(arglist) = sum of arguments&quot;);
+ add_varargs_method(&quot;test&quot;, &amp;example_module::ex_test, &quot;test(arglist) runs a test suite&quot;);
+
+ initialize( &quot;documentation for the example module&quot; );
+ }
+
+ virtual ~example_module() {}
+
+private:
+ Object ex_sum (const Tuple &amp;a) { ... }
+ Object ex_test( const Tuple &amp;a) { ... }
+};
+</pre>
+
+<p>To initialize the extension, you just instantiate one static instance (static so it
+doesn't destroy itself!):</p>
+
+<pre>
+void initexample()
+ {
+ static example_module* example = new example_module;
+ }
+</pre>
+
+<p>The methods can be written to take Tuples as arguments and return Objects. If
+exceptions occur they are trapped for you and a Python exception is generated. So, for
+example, the implementation of ex_sum might be:</p>
+
+<pre>
+Object ex_sum (const Tuple &amp;a)
+ {
+ Float f(0.0);
+ for( int i = 0; i &lt; a.length(); i++ )
+ {
+ Float g(a[i]);
+ f = f + g;
+ }
+ return f;
+ }
+</pre>
+
+<p>class ExtensionModule contains methods to return itself as a Module object, or to
+return its dictionary.</p>
+
+<h4>Creating extension objects</h4>
+
+<p>Creating extension objects is of course harder since you must specify how the object
+behaves and give it methods. This is shown in some detail in the example range.h and range.cxx,
+with the test routine rangetest.cxx, in directory Demo.</p>
+
+<p>Here is a brief overview. You create a class that inherits from PythonExtension
+templated upon itself. You override various methods from PythonExtension to implement
+behaviors, such as getattr, sequence_item, etc. You can also add methods to the object
+that are usable from Python using a similar scheme as for module methods above. </p>
+
+<p>One of the consequences of inheriting from PythonExtension is that you are inheriting
+from PyObject itself. So your class is-a PyObject and instances of it can be passed to the
+Python C API. Note: this example uses the namespace feature of CXX. The Py:: 's are not
+required if you use the namespace instead.</p>
+
+<pre>
+class range: public Py::PythonExtension&lt;range&gt; {
+public:
+ ... constructors, etc.
+
+ ... methods
+ // initializer, see below
+ static void init_type();
+ // override functions from PythonExtension
+ virtual Py::Object repr();
+ virtual Py::Object getattr( const char *name );
+
+ virtual int sequence_length();
+ virtual Py::Object sequence_item( int i );
+ virtual Py::Object sequence_concat( const Py::Object &amp;j );
+ virtual Py::Object sequence_slice( int i, int j );
+
+ // define python methods of this object
+ Py::Object amethod (const Py::Tuple&amp; args);
+ Py::Object value (const Py::Tuple&amp; args);
+ Py::Object assign (const Py::Tuple&amp; args);
+};
+</pre>
+
+<p>
+To initialize the type you provide a static method that you can call from some module's
+initializer. This method sets the name, doc string, and indicates which behaviors it
+supports. It then adds the methods.</p>
+
+<pre>
+void range::init_type()
+{
+ behaviors().name(&quot;range&quot;);
+ behaviors().doc(&quot;range objects: start, stop, step&quot;);
+ behaviors().supportRepr();
+ behaviors().supportGetattr();
+ behaviors().supportSequenceType();
+
+ add_varargs_method(&quot;amethod&quot;, &amp;range::amethod,
+ &quot;demonstrate how to document amethod&quot;);
+ add_varargs_method(&quot;assign&quot;, &amp;range::assign);
+ add_varargs_method(&quot;value&quot;, &amp;range::value);
+}
+</pre>
+
+<h3>Version 3 (June 18, 1999)</h3>
+
+<p>1. CXX compiles with EGCS snapshot 19990616. EGCS requires a standard library class
+random_access_iterator that is not yet available in some other compilers (such as Windows
+VC6). Therefore a new switch:</p>
+
+<p>STANDARD_LIBRARY_HAS_ITERATOR_TRAITS</p>
+
+<p>has been added to CXX_Config.h that you may need to toggle if you get an error on the
+two lines that mention random_access_iterator. The current definition is correct for VC6
+and EGCS-19990616. </p>
+
+<p>2. A new constructor was added to Module to allow construction from a string containing
+the module name. A test was added for this to the demo.</p>
+
+<h3>Version 2 (Dec. 28, 1998)</h3>
+
+<p>Fixed definition of extension type to match 1.5.2. This version will presumably not
+compile with older versions of Python. This can be fixed by using the previous version's
+definition. I did not take the time to find out what these new &quot;flags&quot; are for
+nor put in any methods to deal with them.</p>
+
+<h3>Version 1</h3>
+
+<p>This is an experimental set of files for supporting the creation of Python extensions
+in C++. </p>
+
+<p>Documentation is in progress at <a href="http://xfiles.llnl.gov">http://xfiles.llnl.gov</a>.
+</p>
+
+<p>To use CXX you use the header files in Include, such as CXX_Objects.h or
+CXX_Extensions.h. You must include the sources in Src in your sources to supply parts of
+the CXX classes required.</p>
+
+<p>A demo is included. The Setup file in this directory compiles this demo named
+&quot;example&quot;. To try the demo, which is also a test routine, you import example and
+then execute:</p>
+
+<pre>
+example.test()
+</pre>
+
+<p>You can also play with the extension object whose constructor is named &quot;range&quot;:</p>
+
+<pre>
+s = range(1, 100, 2)
+print s[2] # should print 5
+</pre>
+
+<p>Compilation with Microsoft Visual C++ 5.0 will succeed but only if you have Service
+Pack 3 installed. Compilation has been known to succeed on a Unix system using KCC by
+using:</p>
+
+<pre>
+setenv CCC &quot;KCC -x&quot;
+</pre>
+
+<p>before running makethis.py.</p>
+
+<p>There is also a python.cxx file for making a stand-alone Python containing this
+example, as well as a similar file arraytest.cxx for testing Array.</p>
+
+<p>Comments to [email protected], please.</p>
+
+<p>Barry Scott</p>
+</body>
+</html>
diff --git a/lib/kross/python/cxx/Readme.Kross.txt b/lib/kross/python/cxx/Readme.Kross.txt
new file mode 100644
index 00000000..ec00230a
--- /dev/null
+++ b/lib/kross/python/cxx/Readme.Kross.txt
@@ -0,0 +1,16 @@
+Kross uses PyCXX 5.3.1 (http://cxx.sourceforge.net/)
+to access the Python C API.
+
+Following patches where applied and send back to the PyCXX team.
+
+- Unsigned patch
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1085205&group_id=3180&atid=303180
+- isInstance patch
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1178048&group_id=3180&atid=303180
+- dir patch
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1186676&group_id=3180&atid=303180
+- fixed typos
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1266579&group_id=3180&atid=103180
+ http://sourceforge.net/tracker/index.php?func=detail&aid=1293777&group_id=3180&atid=103180
+
+I also changed the includes to get PyCXX compiled the way we use it.
diff --git a/lib/kross/python/cxx/Version.txt b/lib/kross/python/cxx/Version.txt
new file mode 100644
index 00000000..27be42b3
--- /dev/null
+++ b/lib/kross/python/cxx/Version.txt
@@ -0,0 +1 @@
+PyCxx 5.3.1
diff --git a/lib/kross/python/cxx/cxx_extensions.cxx b/lib/kross/python/cxx/cxx_extensions.cxx
new file mode 100644
index 00000000..f9c942ad
--- /dev/null
+++ b/lib/kross/python/cxx/cxx_extensions.cxx
@@ -0,0 +1,1287 @@
+#include "Extensions.hxx"
+#include "Exception.hxx"
+
+#include <assert.h>
+
+namespace Py
+{
+
+//================================================================================
+//
+// Implementation of MethodTable
+//
+//================================================================================
+
+PyMethodDef MethodTable::method( const char* method_name, PyCFunction f, int flags, const char* doc )
+ {
+ PyMethodDef m;
+ m.ml_name = const_cast<char*>( method_name );
+ m.ml_meth = f;
+ m.ml_flags = flags;
+ m.ml_doc = const_cast<char*>( doc );
+ return m;
+ }
+
+MethodTable::MethodTable()
+ {
+ t.push_back( method( 0, 0, 0, 0 ) );
+ mt = 0;
+ }
+
+MethodTable::~MethodTable()
+ {
+ delete [] mt;
+ }
+
+void MethodTable::add( const char* method_name, PyCFunction f, const char* doc, int flag )
+ {
+ if( !mt )
+ {
+ t.insert( t.end()-1, method( method_name, f, flag, doc ) );
+ }
+ else
+ {
+ throw RuntimeError( "Too late to add a module method!" );
+ }
+ }
+
+PyMethodDef* MethodTable::table()
+ {
+ if( !mt )
+ {
+ int t1size = t.size();
+ mt = new PyMethodDef[t1size];
+ int j = 0;
+ for( std::vector<PyMethodDef>::iterator i = t.begin(); i != t.end(); i++ )
+ {
+ mt[j++] = *i;
+ }
+ }
+ return mt;
+ }
+
+//================================================================================
+//
+// Implementation of ExtensionModule
+//
+//================================================================================
+ExtensionModuleBase::ExtensionModuleBase( const char *name )
+ : module_name( name )
+ , full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : module_name )
+ , method_table()
+ {}
+
+ExtensionModuleBase::~ExtensionModuleBase()
+ {}
+
+const std::string &ExtensionModuleBase::name() const
+ {
+ return module_name;
+ }
+
+const std::string &ExtensionModuleBase::fullName() const
+ {
+ return full_module_name;
+ }
+
+class ExtensionModuleBasePtr : public PythonExtension<ExtensionModuleBasePtr>
+ {
+public:
+ ExtensionModuleBasePtr( ExtensionModuleBase *_module )
+ : module( _module )
+ {}
+ virtual ~ExtensionModuleBasePtr()
+ {}
+
+ ExtensionModuleBase *module;
+ };
+
+
+void ExtensionModuleBase::initialize( const char *module_doc )
+ {
+ PyObject *module_ptr = new ExtensionModuleBasePtr( this );
+
+ Py_InitModule4
+ (
+ const_cast<char *>( module_name.c_str() ), // name
+ method_table.table(), // methods
+ const_cast<char *>( module_doc ), // docs
+ module_ptr, // pass to functions as "self"
+ PYTHON_API_VERSION // API version
+ );
+ }
+
+Py::Module ExtensionModuleBase::module(void) const
+ {
+ return Module( full_module_name );
+ }
+
+Py::Dict ExtensionModuleBase::moduleDictionary(void) const
+ {
+ return module().getDict();
+ }
+
+//--------------------------------------------------------------------------------
+
+//================================================================================
+//
+// Implementation of PythonType
+//
+//================================================================================
+
+extern "C"
+ {
+ static void standard_dealloc(PyObject* p);
+ //
+ // All the following functions redirect the call from Python
+ // onto the matching virtual function in PythonExtensionBase
+ //
+ static int print_handler (PyObject*, FILE *, int);
+ static PyObject* getattr_handler (PyObject*, char*);
+ static int setattr_handler (PyObject*, char*, PyObject*);
+ static PyObject* getattro_handler (PyObject*, PyObject*);
+ static int setattro_handler (PyObject*, PyObject*, PyObject*);
+ static int compare_handler (PyObject*, PyObject*);
+ static PyObject* repr_handler (PyObject*);
+ static PyObject* str_handler (PyObject*);
+ static long hash_handler (PyObject*);
+ static PyObject* call_handler (PyObject*, PyObject*, PyObject*);
+
+#if PY_VERSION_HEX < 0x02050000
+ typedef int Py_ssize_t;
+#endif
+ // Sequence methods
+ static Py_ssize_t sequence_length_handler(PyObject*);
+ static PyObject* sequence_concat_handler(PyObject*,PyObject*);
+ static PyObject* sequence_repeat_handler(PyObject*, Py_ssize_t);
+ static PyObject* sequence_item_handler(PyObject*, Py_ssize_t);
+ static PyObject* sequence_slice_handler(PyObject*, Py_ssize_t, Py_ssize_t);
+ static int sequence_ass_item_handler(PyObject*, Py_ssize_t, PyObject*);
+ static int sequence_ass_slice_handler(PyObject*, Py_ssize_t, Py_ssize_t, PyObject*);
+ // Mapping
+ static Py_ssize_t mapping_length_handler(PyObject*);
+ static PyObject* mapping_subscript_handler(PyObject*, PyObject*);
+ static int mapping_ass_subscript_handler(PyObject*, PyObject*, PyObject*);
+
+ // Numeric methods
+ static int number_nonzero_handler (PyObject*);
+ static PyObject* number_negative_handler (PyObject*);
+ static PyObject* number_positive_handler (PyObject*);
+ static PyObject* number_absolute_handler (PyObject*);
+ static PyObject* number_invert_handler (PyObject*);
+ static PyObject* number_int_handler (PyObject*);
+ static PyObject* number_float_handler (PyObject*);
+ static PyObject* number_long_handler (PyObject*);
+ static PyObject* number_oct_handler (PyObject*);
+ static PyObject* number_hex_handler (PyObject*);
+ static PyObject* number_add_handler (PyObject*, PyObject*);
+ static PyObject* number_subtract_handler (PyObject*, PyObject*);
+ static PyObject* number_multiply_handler (PyObject*, PyObject*);
+ static PyObject* number_divide_handler (PyObject*, PyObject*);
+ static PyObject* number_remainder_handler (PyObject*, PyObject*);
+ static PyObject* number_divmod_handler (PyObject*, PyObject*);
+ static PyObject* number_lshift_handler (PyObject*, PyObject*);
+ static PyObject* number_rshift_handler (PyObject*, PyObject*);
+ static PyObject* number_and_handler (PyObject*, PyObject*);
+ static PyObject* number_xor_handler (PyObject*, PyObject*);
+ static PyObject* number_or_handler (PyObject*, PyObject*);
+ static PyObject* number_power_handler(PyObject*, PyObject*, PyObject*);
+
+ // Buffer
+ static Py_ssize_t buffer_getreadbuffer_handler (PyObject*, Py_ssize_t, void**);
+ static Py_ssize_t buffer_getwritebuffer_handler (PyObject*, Py_ssize_t, void**);
+ static Py_ssize_t buffer_getsegcount_handler (PyObject*, Py_ssize_t*);
+ }
+
+
+extern "C" void standard_dealloc( PyObject* p )
+ {
+ PyMem_DEL( p );
+ }
+
+void PythonType::supportSequenceType()
+ {
+ if( !sequence_table )
+ {
+ sequence_table = new PySequenceMethods;
+ table->tp_as_sequence = sequence_table;
+ sequence_table->sq_length = sequence_length_handler;
+ sequence_table->sq_concat = sequence_concat_handler;
+ sequence_table->sq_repeat = sequence_repeat_handler;
+ sequence_table->sq_item = sequence_item_handler;
+ sequence_table->sq_slice = sequence_slice_handler;
+
+ sequence_table->sq_ass_item = sequence_ass_item_handler; // BAS setup seperately?
+ sequence_table->sq_ass_slice = sequence_ass_slice_handler; // BAS setup seperately?
+ }
+ }
+
+void PythonType::supportMappingType()
+ {
+ if( !mapping_table )
+ {
+ mapping_table = new PyMappingMethods;
+ table->tp_as_mapping = mapping_table;
+ mapping_table->mp_length = mapping_length_handler;
+ mapping_table->mp_subscript = mapping_subscript_handler;
+ mapping_table->mp_ass_subscript = mapping_ass_subscript_handler; // BAS setup seperately?
+ }
+ }
+
+void PythonType::supportNumberType()
+ {
+ if( !number_table )
+ {
+ number_table = new PyNumberMethods;
+ table->tp_as_number = number_table;
+ number_table->nb_add = number_add_handler;
+ number_table->nb_subtract = number_subtract_handler;
+ number_table->nb_multiply = number_multiply_handler;
+ number_table->nb_divide = number_divide_handler;
+ number_table->nb_remainder = number_remainder_handler;
+ number_table->nb_divmod = number_divmod_handler;
+ number_table->nb_power = number_power_handler;
+ number_table->nb_negative = number_negative_handler;
+ number_table->nb_positive = number_positive_handler;
+ number_table->nb_absolute = number_absolute_handler;
+ number_table->nb_nonzero = number_nonzero_handler;
+ number_table->nb_invert = number_invert_handler;
+ number_table->nb_lshift = number_lshift_handler;
+ number_table->nb_rshift = number_rshift_handler;
+ number_table->nb_and = number_and_handler;
+ number_table->nb_xor = number_xor_handler;
+ number_table->nb_or = number_or_handler;
+ number_table->nb_coerce = 0;
+ number_table->nb_int = number_int_handler;
+ number_table->nb_long = number_long_handler;
+ number_table->nb_float = number_float_handler;
+ number_table->nb_oct = number_oct_handler;
+ number_table->nb_hex = number_hex_handler;
+ }
+ }
+
+void PythonType::supportBufferType()
+ {
+ if( !buffer_table )
+ {
+ buffer_table = new PyBufferProcs;
+ table->tp_as_buffer = buffer_table;
+ buffer_table->bf_getreadbuffer = buffer_getreadbuffer_handler;
+ buffer_table->bf_getwritebuffer = buffer_getwritebuffer_handler;
+ buffer_table->bf_getsegcount = buffer_getsegcount_handler;
+ }
+ }
+
+// if you define one sequence method you must define
+// all of them except the assigns
+
+PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name )
+ : table( new PyTypeObject )
+ , sequence_table( NULL )
+ , mapping_table( NULL )
+ , number_table( NULL )
+ , buffer_table( NULL )
+ {
+ *reinterpret_cast<PyObject*>( table ) = py_object_initializer;
+ table->ob_type = _Type_Type();
+ table->ob_size = 0;
+ table->tp_name = const_cast<char *>( default_name );
+ table->tp_basicsize = basic_size;
+ table->tp_itemsize = itemsize;
+ table->tp_dealloc = ( destructor ) standard_dealloc;
+ table->tp_print = 0;
+ table->tp_getattr = 0;
+ table->tp_setattr = 0;
+ table->tp_compare = 0;
+ table->tp_repr = 0;
+ table->tp_as_number = 0;
+ table->tp_as_sequence = 0;
+ table->tp_as_mapping = 0;
+ table->tp_hash = 0;
+ table->tp_call = 0;
+ table->tp_str = 0;
+ table->tp_getattro = 0;
+ table->tp_setattro = 0;
+ table->tp_as_buffer = 0;
+ table->tp_flags = 0L;
+ table->tp_doc = 0;
+#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 0)
+ // first use in 2.0
+ table->tp_traverse = 0L;
+ table->tp_clear = 0L;
+#else
+ table->tp_xxx5 = 0L;
+ table->tp_xxx6 = 0L;
+#endif
+#if PY_MAJOR_VERSION > 2 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 1)
+ // first defined in 2.1
+ table->tp_richcompare = 0L;
+ table->tp_weaklistoffset = 0L;
+#else
+ table->tp_xxx7 = 0L;
+ table->tp_xxx8 = 0L;
+#endif
+
+#ifdef COUNT_ALLOCS
+ table->tp_alloc = 0;
+ table->tp_free = 0;
+ table->tp_maxalloc = 0;
+ table->tp_next = 0;
+#endif
+ }
+
+PythonType::~PythonType( )
+ {
+ delete table;
+ delete sequence_table;
+ delete mapping_table;
+ delete number_table;
+ delete buffer_table;
+ }
+
+PyTypeObject* PythonType::type_object( ) const
+ {return table;}
+
+void PythonType::name( const char* nam )
+ {
+ table->tp_name = const_cast<char *>( nam );
+ }
+
+const char *PythonType::getName() const
+ {
+ return table->tp_name;
+ }
+
+void PythonType::doc( const char* d )
+ {
+ table->tp_doc = const_cast<char *>( d );
+ }
+
+const char *PythonType::getDoc() const
+ {
+ return table->tp_doc;
+ }
+
+void PythonType::dealloc( void( *f )( PyObject* ))
+ {
+ table->tp_dealloc = f;
+ }
+
+void PythonType::supportPrint()
+ {
+ table->tp_print = print_handler;
+ }
+
+void PythonType::supportGetattr()
+ {
+ table->tp_getattr = getattr_handler;
+ }
+
+void PythonType::supportSetattr()
+ {
+ table->tp_setattr = setattr_handler;
+ }
+
+void PythonType::supportGetattro()
+ {
+ table->tp_getattro = getattro_handler;
+ }
+
+void PythonType::supportSetattro()
+ {
+ table->tp_setattro = setattro_handler;
+ }
+
+void PythonType::supportCompare()
+ {
+ table->tp_compare = compare_handler;
+ }
+
+void PythonType::supportRepr()
+ {
+ table->tp_repr = repr_handler;
+ }
+
+void PythonType::supportStr()
+ {
+ table->tp_str = str_handler;
+ }
+
+void PythonType::supportHash()
+ {
+ table->tp_hash = hash_handler;
+ }
+
+void PythonType::supportCall()
+ {
+ table->tp_call = call_handler;
+ }
+
+//--------------------------------------------------------------------------------
+//
+// Handlers
+//
+//--------------------------------------------------------------------------------
+extern "C" int print_handler( PyObject *self, FILE *fp, int flags )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->print( fp, flags );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* getattr_handler( PyObject *self, char *name )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->getattr( name ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->setattr( name, Py::Object( value ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* getattro_handler( PyObject *self, PyObject *name )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->getattro( Py::Object( name ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->setattro( Py::Object( name ), Py::Object( value ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" int compare_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->compare( Py::Object( other ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* repr_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->repr() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* str_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->str() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" long hash_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->hash();
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* call_handler( PyObject *self, PyObject *args, PyObject *kw )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->call( Py::Object( args ), Py::Object( kw ) ) );
+ if( kw != NULL )
+ return new_reference_to( p->call( Py::Object( args ), Py::Object( kw ) ) );
+ else
+ return new_reference_to( p->call( Py::Object( args ), Py::Object() ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+
+// Sequence methods
+extern "C" Py_ssize_t sequence_length_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->sequence_length();
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* sequence_concat_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->sequence_concat( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* sequence_repeat_handler( PyObject *self, Py_ssize_t count )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->sequence_repeat( count ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* sequence_item_handler( PyObject *self, Py_ssize_t index )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->sequence_item( index ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* sequence_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->sequence_slice( first, last ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->sequence_ass_item( index, Py::Object( value ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" int sequence_ass_slice_handler( PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *value )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->sequence_ass_slice( first, last, Py::Object( value ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+// Mapping
+extern "C" Py_ssize_t mapping_length_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->mapping_length();
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* mapping_subscript_handler( PyObject *self, PyObject *key )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->mapping_subscript( Py::Object( key ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->mapping_ass_subscript( Py::Object( key ), Py::Object( value ) );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+// Number
+extern "C" int number_nonzero_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->number_nonzero();
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_negative_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_negative() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_positive_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_positive() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_absolute_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_absolute() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_invert_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_invert() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_int_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_int() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_float_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_float() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_long_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_long() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_oct_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_oct() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_hex_handler( PyObject *self )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_hex() );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_add_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_add( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_subtract_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_subtract( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_multiply_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_multiply( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_divide_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_divide( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_remainder_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_remainder( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_divmod_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_divmod( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_lshift_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_lshift( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_rshift_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_rshift( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_and_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_and( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_xor_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_xor( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_or_handler( PyObject *self, PyObject *other )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_or( Py::Object( other ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+extern "C" PyObject* number_power_handler( PyObject *self, PyObject *x1, PyObject *x2 )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return new_reference_to( p->number_power( Py::Object( x1 ), Py::Object( x2 ) ) );
+ }
+ catch( Py::Exception & )
+ {
+ return NULL; // indicate error
+ }
+ }
+
+// Buffer
+extern "C" Py_ssize_t buffer_getreadbuffer_handler( PyObject *self, Py_ssize_t index, void **pp )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->buffer_getreadbuffer( index, pp );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" Py_ssize_t buffer_getwritebuffer_handler( PyObject *self, Py_ssize_t index, void **pp )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ return p->buffer_getwritebuffer( index, pp );
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+extern "C" Py_ssize_t buffer_getsegcount_handler( PyObject *self, Py_ssize_t *count )
+ {
+ try
+ {
+ PythonExtensionBase *p = static_cast<PythonExtensionBase *>( self );
+ int i_count = *count;
+ Py_ssize_t r = p->buffer_getsegcount( &i_count );
+ *count = i_count;
+ return r;
+ }
+ catch( Py::Exception & )
+ {
+ return -1; // indicate error
+ }
+ }
+
+
+//================================================================================
+//
+// Implementation of PythonExtensionBase
+//
+//================================================================================
+#define missing_method( method ) \
+throw RuntimeError( "Extension object does not support method " #method );
+
+PythonExtensionBase::PythonExtensionBase()
+ {
+ }
+
+PythonExtensionBase::~PythonExtensionBase()
+ {
+ assert( ob_refcnt == 0 );
+ }
+
+int PythonExtensionBase::print( FILE *, int )
+ { missing_method( print ); return -1; }
+
+int PythonExtensionBase::setattr( const char*, const Py::Object & )
+ { missing_method( setattr ); return -1; }
+
+Py::Object PythonExtensionBase::getattro( const Py::Object & )
+ { missing_method( getattro ); return Py::Nothing(); }
+
+int PythonExtensionBase::setattro( const Py::Object &, const Py::Object & )
+ { missing_method( setattro ); return -1; }
+
+int PythonExtensionBase::compare( const Py::Object & )
+ { missing_method( compare ); return -1; }
+
+Py::Object PythonExtensionBase::repr()
+ { missing_method( repr ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::str()
+ { missing_method( str ); return Py::Nothing(); }
+
+long PythonExtensionBase::hash()
+ { missing_method( hash ); return -1; }
+
+Py::Object PythonExtensionBase::call( const Py::Object &, const Py::Object & )
+ { missing_method( call ); return Py::Nothing(); }
+
+
+// Sequence methods
+int PythonExtensionBase::sequence_length()
+ { missing_method( sequence_length ); return -1; }
+
+Py::Object PythonExtensionBase::sequence_concat( const Py::Object & )
+ { missing_method( sequence_concat ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::sequence_repeat( int )
+ { missing_method( sequence_repeat ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::sequence_item( int )
+ { missing_method( sequence_item ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::sequence_slice( int, int )
+ { missing_method( sequence_slice ); return Py::Nothing(); }
+
+int PythonExtensionBase::sequence_ass_item( int, const Py::Object & )
+ { missing_method( sequence_ass_item ); return -1; }
+
+int PythonExtensionBase::sequence_ass_slice( int, int, const Py::Object & )
+ { missing_method( sequence_ass_slice ); return -1; }
+
+
+// Mapping
+int PythonExtensionBase::mapping_length()
+ { missing_method( mapping_length ); return -1; }
+
+Py::Object PythonExtensionBase::mapping_subscript( const Py::Object & )
+ { missing_method( mapping_subscript ); return Py::Nothing(); }
+
+int PythonExtensionBase::mapping_ass_subscript( const Py::Object &, const Py::Object & )
+ { missing_method( mapping_ass_subscript ); return -1; }
+
+
+// Number
+int PythonExtensionBase::number_nonzero()
+ { missing_method( number_nonzero ); return -1; }
+
+Py::Object PythonExtensionBase::number_negative()
+ { missing_method( number_negative ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_positive()
+ { missing_method( number_positive ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_absolute()
+ { missing_method( number_absolute ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_invert()
+ { missing_method( number_invert ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_int()
+ { missing_method( number_int ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_float()
+ { missing_method( number_float ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_long()
+ { missing_method( number_long ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_oct()
+ { missing_method( number_oct ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_hex()
+ { missing_method( number_hex ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_add( const Py::Object & )
+ { missing_method( number_add ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_subtract( const Py::Object & )
+ { missing_method( number_subtract ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_multiply( const Py::Object & )
+ { missing_method( number_multiply ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_divide( const Py::Object & )
+ { missing_method( number_divide ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_remainder( const Py::Object & )
+ { missing_method( number_remainder ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_divmod( const Py::Object & )
+ { missing_method( number_divmod ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_lshift( const Py::Object & )
+ { missing_method( number_lshift ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_rshift( const Py::Object & )
+ { missing_method( number_rshift ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_and( const Py::Object & )
+ { missing_method( number_and ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_xor( const Py::Object & )
+ { missing_method( number_xor ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_or( const Py::Object & )
+ { missing_method( number_or ); return Py::Nothing(); }
+
+Py::Object PythonExtensionBase::number_power( const Py::Object &, const Py::Object & )
+ { missing_method( number_power ); return Py::Nothing(); }
+
+
+// Buffer
+int PythonExtensionBase::buffer_getreadbuffer( int, void** )
+ { missing_method( buffer_getreadbuffer ); return -1; }
+
+int PythonExtensionBase::buffer_getwritebuffer( int, void** )
+ { missing_method( buffer_getwritebuffer ); return -1; }
+
+int PythonExtensionBase::buffer_getsegcount( int* )
+ { missing_method( buffer_getsegcount ); return -1; }
+
+//--------------------------------------------------------------------------------
+//
+// Method call handlers for
+// PythonExtensionBase
+// ExtensionModuleBase
+//
+//--------------------------------------------------------------------------------
+
+extern "C" PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords )
+ {
+ try
+ {
+ Tuple self_and_name_tuple( _self_and_name_tuple );
+
+ PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
+ void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject );
+ if( self_as_void == NULL )
+ return NULL;
+
+ ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void );
+
+ String py_name( self_and_name_tuple[1] );
+ std::string name( py_name.as_std_string() );
+
+ Tuple args( _args );
+ if( _keywords == NULL )
+ {
+ Dict keywords; // pass an empty dict
+
+ Object result( self->invoke_method_keyword( name, args, keywords ) );
+ return new_reference_to( result.ptr() );
+ }
+ else
+ {
+ Dict keywords( _keywords );
+
+ Object result( self->invoke_method_keyword( name, args, keywords ) );
+ return new_reference_to( result.ptr() );
+ }
+ }
+ catch( Exception & )
+ {
+ return 0;
+ }
+ }
+
+extern "C" PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args )
+ {
+ try
+ {
+ Tuple self_and_name_tuple( _self_and_name_tuple );
+
+ PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
+ void *self_as_void = PyCObject_AsVoidPtr( self_in_cobject );
+ if( self_as_void == NULL )
+ return NULL;
+
+ ExtensionModuleBase *self = static_cast<ExtensionModuleBase *>( self_as_void );
+
+ String py_name( self_and_name_tuple[1] );
+ std::string name( py_name.as_std_string() );
+
+ Tuple args( _args );
+
+ Object result( self->invoke_method_varargs( name, args ) );
+
+ return new_reference_to( result.ptr() );
+ }
+ catch( Exception & )
+ {
+ return 0;
+ }
+ }
+
+extern "C" void do_not_dealloc( void * )
+ {}
+
+
+//--------------------------------------------------------------------------------
+//
+// ExtensionExceptionType
+//
+//--------------------------------------------------------------------------------
+ExtensionExceptionType::ExtensionExceptionType()
+ : Py::Object()
+ {
+ }
+
+void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name )
+ {
+ std::string module_name( module.fullName() );
+ module_name += ".";
+ module_name += name;
+
+ set( PyErr_NewException( const_cast<char *>( module_name.c_str() ), NULL, NULL ), true );
+ }
+
+ExtensionExceptionType::~ExtensionExceptionType()
+ {
+ }
+
+Exception::Exception( ExtensionExceptionType &exception, const std::string& reason )
+ {
+ PyErr_SetString (exception.ptr(), reason.c_str());
+ }
+
+
+} // end of namespace Py
diff --git a/lib/kross/python/cxx/cxxextensions.c b/lib/kross/python/cxx/cxxextensions.c
new file mode 100644
index 00000000..6f369b2d
--- /dev/null
+++ b/lib/kross/python/cxx/cxxextensions.c
@@ -0,0 +1,19 @@
+/*
+ Copyright 1998 The Regents of the University of California.
+ All rights reserved. See Legal.htm for full text and disclaimer.
+*/
+
+#include "Python.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+PyObject py_object_initializer = {PyObject_HEAD_INIT(0)};
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
+
diff --git a/lib/kross/python/cxx/cxxsupport.cxx b/lib/kross/python/cxx/cxxsupport.cxx
new file mode 100644
index 00000000..61329b60
--- /dev/null
+++ b/lib/kross/python/cxx/cxxsupport.cxx
@@ -0,0 +1,142 @@
+//----------------------------------*-C++-*----------------------------------//
+// Copyright 1998 The Regents of the University of California.
+// All rights reserved. See Legal.htm for full text and disclaimer.
+//---------------------------------------------------------------------------//
+
+#include "Objects.hxx"
+namespace Py {
+
+Py_UNICODE unicode_null_string[1] = { 0 };
+
+Type Object::type () const
+ {
+ return Type (PyObject_Type (p), true);
+ }
+
+String Object::str () const
+ {
+ return String (PyObject_Str (p), true);
+ }
+
+String Object::repr () const
+ {
+ return String (PyObject_Repr (p), true);
+ }
+
+std::string Object::as_string() const
+ {
+ return static_cast<std::string>(str());
+ }
+
+List Object::dir () const
+ {
+ return List (PyObject_Dir (p), true);
+ }
+
+bool Object::isType (const Type& t) const
+ {
+ return type ().ptr() == t.ptr();
+ }
+
+Char::operator String() const
+ {
+ return String(ptr());
+ }
+
+// TMM: non-member operaters for iterators - see above
+// I've also made a bug fix in respect to the cxx code
+// (dereffed the left.seq and right.seq comparison)
+bool operator==(const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.eql( right );
+ }
+
+bool operator!=(const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.neq( right );
+ }
+
+bool operator< (const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.lss( right );
+ }
+
+bool operator> (const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.gtr( right );
+ }
+
+bool operator<=(const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.leq( right );
+ }
+
+bool operator>=(const Sequence::iterator& left, const Sequence::iterator& right)
+ {
+ return left.geq( right );
+ }
+
+// now for const_iterator
+bool operator==(const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.eql( right );
+ }
+
+bool operator!=(const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.neq( right );
+ }
+
+bool operator< (const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.lss( right );
+ }
+
+bool operator> (const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.gtr( right );
+ }
+
+bool operator<=(const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.leq( right );
+ }
+
+bool operator>=(const Sequence::const_iterator& left, const Sequence::const_iterator& right)
+ {
+ return left.geq( right );
+ }
+
+// For mappings:
+bool operator==(const Mapping::iterator& left, const Mapping::iterator& right)
+ {
+ return left.eql( right );
+ }
+
+bool operator!=(const Mapping::iterator& left, const Mapping::iterator& right)
+ {
+ return left.neq( right );
+ }
+
+// now for const_iterator
+bool operator==(const Mapping::const_iterator& left, const Mapping::const_iterator& right)
+ {
+ return left.eql( right );
+ }
+
+bool operator!=(const Mapping::const_iterator& left, const Mapping::const_iterator& right)
+ {
+ return left.neq( right );
+ }
+
+// TMM: 31May'01 - Added the #ifndef so I can exclude iostreams.
+#ifndef CXX_NO_IOSTREAMS
+// output
+
+std::ostream& operator<< (std::ostream& os, const Object& ob)
+ {
+ return (os << static_cast<std::string>(ob.str()));
+ }
+#endif
+
+} // Py