diff options
Diffstat (limited to 'lib/kross/python/cxx/Extensions.hxx')
-rw-r--r-- | lib/kross/python/cxx/Extensions.hxx | 756 |
1 files changed, 0 insertions, 756 deletions
diff --git a/lib/kross/python/cxx/Extensions.hxx b/lib/kross/python/cxx/Extensions.hxx deleted file mode 100644 index 5c7c2bcf3..000000000 --- a/lib/kross/python/cxx/Extensions.hxx +++ /dev/null @@ -1,756 +0,0 @@ -//---------------------------------------------------------------------------// -// 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<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(); - 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<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( 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<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 |