//----------------------------------------------------------------------------- // // Copyright (c) 1998 - 2007, The Regents of the University of California // Produced at the Lawrence Livermore National Laboratory // All rights reserved. // // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The // full copyright notice is contained in the file COPYRIGHT located at the root // of the PyCXX distribution. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, // this list of conditions and the disclaimer below. // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the disclaimer (as noted below) in the // documentation and/or materials provided with the distribution. // - Neither the name of the UC/LLNL nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF // CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. // //----------------------------------------------------------------------------- #include "CXX/Extensions.hxx" #include "CXX/Exception.hxx" #include "CXX/Objects.hxx" #include #ifdef PYCXX_DEBUG // // Functions useful when debugging PyCXX // void bpt( void ) { } void printRefCount( PyObject *obj ) { std::cout << "RefCount of 0x" << std::hex << reinterpret_cast< unsigned long >( obj ) << std::dec << " is " << Py_REFCNT( obj ) << std::endl; } #endif namespace Py { void Object::validate() { // release pointer if not the right type if( !accepts( p ) ) { #if defined( _CPPRTTI ) || defined( __GNUG__ ) std::string s( "PyCXX: Error creating object of type " ); s += (typeid( *this )).name(); if( p != NULL ) { String from_repr = repr(); s += " from "; s += from_repr.as_std_string(); } else { s += " from (nil)"; } #endif release(); // If error message already set ifPyErrorThrowCxxException(); // Better error message if RTTI available #if defined( _CPPRTTI ) || defined( __GNUG__ ) throw TypeError( s ); #else throw TypeError( "PyCXX: type error." ); #endif } } //================================================================================ // // Implementation of MethodTable // //================================================================================ PyMethodDef MethodTable::method( const char *method_name, PyCFunction f, int flags, const char *doc ) { PyMethodDef m; m.ml_name = const_cast( method_name ); m.ml_meth = f; m.ml_flags = flags; m.ml_doc = const_cast( doc ); return m; } MethodTable::MethodTable() { t.push_back( method( 0, 0, 0, 0 ) ); mt = NULL; } 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 ) { Py_ssize_t t1size = t.size(); mt = new PyMethodDef[ t1size ]; int j = 0; for( std::vector::iterator i = t.begin(); i != t.end(); i++ ) { mt[ j++ ] = *i; } } return mt; } //================================================================================ // // Implementation of ExtensionModule // //================================================================================ ExtensionModuleBase::ExtensionModuleBase( const char *name ) : m_module_name( name ) #if defined( Py_LIMITED_API ) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 12) , m_full_module_name( m_module_name ) #else , m_full_module_name( __Py_PackageContext() != NULL ? std::string( __Py_PackageContext() ) : m_module_name ) #endif , m_method_table() //m_module_def , m_module( NULL ) {} ExtensionModuleBase::~ExtensionModuleBase() {} const std::string &ExtensionModuleBase::name() const { return m_module_name; } const std::string &ExtensionModuleBase::fullName() const { return m_full_module_name; } class ExtensionModuleBasePtr : public PythonExtension { public: ExtensionModuleBasePtr( ExtensionModuleBase *_module ) : module( _module ) {} virtual ~ExtensionModuleBasePtr() {} ExtensionModuleBase *module; }; void initExceptions(); void ExtensionModuleBase::initialize( const char *module_doc ) { // init the exception code initExceptions(); memset( &m_module_def, 0, sizeof( m_module_def ) ); m_module_def.m_name = const_cast( m_module_name.c_str() ); m_module_def.m_doc = const_cast( module_doc ); m_module_def.m_methods = m_method_table.table(); // where does module_ptr get passed in? m_module = PyModule_Create( &m_module_def ); } Module ExtensionModuleBase::module( void ) const { return Module( m_module ); } Dict ExtensionModuleBase::moduleDictionary( void ) const { return module().getDict(); } Object ExtensionModuleBase::moduleObject( void ) const { return Object( m_module ); } //================================================================================ // // 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 // #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 static int print_handler( PyObject *, FILE *, int ); #endif 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 PyObject *rich_compare_handler( PyObject *, PyObject *, int ); static PyObject *repr_handler( PyObject * ); static PyObject *str_handler( PyObject * ); static Py_hash_t hash_handler( PyObject * ); static PyObject *call_handler( PyObject *, PyObject *, PyObject * ); static PyObject *iter_handler( PyObject * ); static PyObject *iternext_handler( PyObject * ); // 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 int sequence_ass_item_handler( PyObject *, Py_ssize_t, PyObject * ); static PyObject *sequence_inplace_concat_handler( PyObject *, PyObject * ); static PyObject *sequence_inplace_repeat_handler( PyObject *, Py_ssize_t ); static int sequence_contains_handler( PyObject *, 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 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_add_handler( PyObject *, PyObject * ); static PyObject *number_subtract_handler( PyObject *, PyObject * ); static PyObject *number_multiply_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 * ); static PyObject *number_floor_divide_handler( PyObject *, PyObject * ); static PyObject *number_true_divide_handler( PyObject *, PyObject * ); static PyObject *number_index_handler( PyObject * ); #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 static PyObject *number_matrix_multiply_handler( PyObject *, PyObject * ); #endif static PyObject *number_inplace_add_handler( PyObject *, PyObject * ); static PyObject *number_inplace_subtract_handler( PyObject *, PyObject * ); static PyObject *number_inplace_multiply_handler( PyObject *, PyObject * ); static PyObject *number_inplace_remainder_handler( PyObject *, PyObject * ); static PyObject *number_inplace_power_handler( PyObject *, PyObject *, PyObject * ); static PyObject *number_inplace_lshift_handler( PyObject *, PyObject * ); static PyObject *number_inplace_rshift_handler( PyObject *, PyObject * ); static PyObject *number_inplace_and_handler( PyObject *, PyObject * ); static PyObject *number_inplace_xor_handler( PyObject *, PyObject * ); static PyObject *number_inplace_or_handler( PyObject *, PyObject * ); static PyObject *number_inplace_floor_divide_handler( PyObject *, PyObject * ); static PyObject *number_inplace_true_divide_handler( PyObject *, PyObject * ); #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 static PyObject *number_inplace_matrix_multiply_handler( PyObject *, PyObject * ); #endif // Buffer #if !defined( Py_LIMITED_API ) static int buffer_get_handler( PyObject *, Py_buffer *, int ); static void buffer_release_handler( PyObject *, Py_buffer * ); #endif } extern "C" void standard_dealloc( PyObject *p ) { PyMem_DEL( p ); } bool PythonType::readyType() { #if defined( Py_LIMITED_API ) if( !tp_object ) { std::vector spec_slots( slots.size() + 1 ); int index = 0; for (std::unordered_map::const_iterator i = slots.cbegin(); i != slots.cend(); i++) { spec_slots[ index ].slot = i->first; spec_slots[ index ].pfunc = i->second; index++; } spec_slots[ index ].slot = 0; spec->slots = spec_slots.data(); tp_object = reinterpret_cast( PyType_FromSpec(spec) ); } return tp_object != NULL; #else return PyType_Ready( table ) >= 0; #endif } #if defined( Py_LIMITED_API ) #define FILL_SEQUENCE_SLOT(slot) \ if( methods_to_support&support_sequence_ ## slot ) { \ slots[ Py_sq_ ## slot ] = reinterpret_cast( sequence_ ## slot ## _handler ); \ } #else #define FILL_SEQUENCE_SLOT(slot) \ if( methods_to_support&support_sequence_ ## slot ) { \ sequence_table->sq_ ## slot = sequence_ ## slot ## _handler; \ } #endif PythonType &PythonType::supportSequenceType( int methods_to_support ) { #if !defined( Py_LIMITED_API ) if(sequence_table) { return *this; } sequence_table = new PySequenceMethods; memset( sequence_table, 0, sizeof( PySequenceMethods ) ); // ensure new fields are 0 table->tp_as_sequence = sequence_table; #endif FILL_SEQUENCE_SLOT(length) FILL_SEQUENCE_SLOT(concat) FILL_SEQUENCE_SLOT(repeat) FILL_SEQUENCE_SLOT(item) FILL_SEQUENCE_SLOT(ass_item) FILL_SEQUENCE_SLOT(inplace_concat) FILL_SEQUENCE_SLOT(inplace_repeat) FILL_SEQUENCE_SLOT(contains) return *this; } #undef FILL_SEQUENCE_SLOT #if defined( Py_LIMITED_API ) #define FILL_MAPPING_SLOT(slot) \ if( methods_to_support&support_mapping_ ## slot ) { \ slots[ Py_mp_ ## slot ] = reinterpret_cast( mapping_ ## slot ## _handler ); \ } #else #define FILL_MAPPING_SLOT(slot) \ if( methods_to_support&support_mapping_ ## slot ) { \ mapping_table->mp_ ## slot = mapping_ ## slot ## _handler; \ } #endif PythonType &PythonType::supportMappingType( int methods_to_support ) { #if !defined( Py_LIMITED_API ) if( mapping_table ) { return *this; } mapping_table = new PyMappingMethods; memset( mapping_table, 0, sizeof( PyMappingMethods ) ); // ensure new fields are 0 table->tp_as_mapping = mapping_table; #endif FILL_MAPPING_SLOT(length) FILL_MAPPING_SLOT(subscript) FILL_MAPPING_SLOT(ass_subscript) return *this; } #undef FILL_MAPPING_SLOT #if defined( Py_LIMITED_API ) #define FILL_NUMBER_SLOT(slot) \ if( methods_to_support&support_number_ ## slot ) { \ slots[ Py_nb_ ## slot ] = reinterpret_cast( number_ ## slot ## _handler ); \ } #define FILL_NUMBER_INPLACE_SLOT(slot) \ if( inplace_methods_to_support&support_number_ ## slot ) { \ slots[ Py_nb_ ## slot ] = reinterpret_cast( number_ ## slot ## _handler ); \ } #else #define FILL_NUMBER_SLOT(slot) \ if( methods_to_support&support_number_ ## slot ) { \ number_table->nb_ ## slot = number_ ## slot ## _handler; \ } #define FILL_NUMBER_INPLACE_SLOT(slot) \ if( inplace_methods_to_support&support_number_ ## slot ) { \ number_table->nb_ ## slot = number_ ## slot ## _handler; \ } #endif PythonType &PythonType::supportNumberType( int methods_to_support, int inplace_methods_to_support ) { #if !defined( Py_LIMITED_API ) if( number_table ) { return *this; } number_table = new PyNumberMethods; memset( number_table, 0, sizeof( PyNumberMethods ) ); // ensure new fields are 0 table->tp_as_number = number_table; #endif FILL_NUMBER_SLOT(add) FILL_NUMBER_SLOT(subtract) FILL_NUMBER_SLOT(multiply) FILL_NUMBER_SLOT(remainder) FILL_NUMBER_SLOT(divmod) FILL_NUMBER_SLOT(power) FILL_NUMBER_SLOT(negative) FILL_NUMBER_SLOT(positive) FILL_NUMBER_SLOT(absolute) FILL_NUMBER_SLOT(invert) FILL_NUMBER_SLOT(lshift) FILL_NUMBER_SLOT(rshift) FILL_NUMBER_SLOT(and) FILL_NUMBER_SLOT(xor) FILL_NUMBER_SLOT(or) FILL_NUMBER_SLOT(int) FILL_NUMBER_SLOT(float) FILL_NUMBER_SLOT(floor_divide) FILL_NUMBER_SLOT(true_divide) FILL_NUMBER_SLOT(index) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 FILL_NUMBER_SLOT(matrix_multiply) #endif FILL_NUMBER_INPLACE_SLOT(inplace_add) FILL_NUMBER_INPLACE_SLOT(inplace_subtract) FILL_NUMBER_INPLACE_SLOT(inplace_multiply) FILL_NUMBER_INPLACE_SLOT(inplace_remainder) FILL_NUMBER_INPLACE_SLOT(inplace_power) FILL_NUMBER_INPLACE_SLOT(inplace_lshift) FILL_NUMBER_INPLACE_SLOT(inplace_rshift) FILL_NUMBER_INPLACE_SLOT(inplace_and) FILL_NUMBER_INPLACE_SLOT(inplace_xor) FILL_NUMBER_INPLACE_SLOT(inplace_or) FILL_NUMBER_INPLACE_SLOT(inplace_floor_divide) FILL_NUMBER_INPLACE_SLOT(inplace_true_divide) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 FILL_NUMBER_INPLACE_SLOT(inplace_matrix_multiply) #endif return *this; } #undef FILL_NUMBER_SLOT #if !defined( Py_LIMITED_API ) PythonType &PythonType::supportBufferType( int methods_to_support ) { if( !buffer_table ) { buffer_table = new PyBufferProcs; memset( buffer_table, 0, sizeof( PyBufferProcs ) ); // ensure new fields are 0 table->tp_as_buffer = buffer_table; if( methods_to_support&support_buffer_getbuffer ) { buffer_table->bf_getbuffer = buffer_get_handler; } if( methods_to_support&support_buffer_releasebuffer ) { buffer_table->bf_releasebuffer = buffer_release_handler; } } return *this; } #endif // if you define one sequence method you must define // all of them except the assigns #if defined( Py_LIMITED_API ) PythonType::PythonType( size_t basic_size, int itemsize, const char *default_name ) : spec( new PyType_Spec ) { memset( spec, 0, sizeof( PyType_Spec ) ); spec->name = const_cast( default_name ); spec->basicsize = basic_size; spec->itemsize = itemsize; spec->flags = Py_TPFLAGS_DEFAULT; slots[ Py_tp_dealloc ] = reinterpret_cast( standard_dealloc ); tp_object = 0; } #else 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 ) { // PyTypeObject is defined in /Include/object.h memset( table, 0, sizeof( PyTypeObject ) ); // ensure new fields are 0 *reinterpret_cast( table ) = py_object_initializer; reinterpret_cast( table )->ob_type = _Type_Type(); // QQQ table->ob_size = 0; table->tp_name = const_cast( default_name ); table->tp_basicsize = basic_size; table->tp_itemsize = itemsize; // Methods to implement standard operations table->tp_dealloc = (destructor)standard_dealloc; #if PY_VERSION_HEX < 0x03080000 table->tp_print = 0; #else table->tp_vectorcall_offset = 0; #endif table->tp_getattr = 0; table->tp_setattr = 0; table->tp_repr = 0; // Method suites for standard classes table->tp_as_number = 0; table->tp_as_sequence = 0; table->tp_as_mapping = 0; // More standard operations (here for binary compatibility) table->tp_hash = 0; table->tp_call = 0; table->tp_str = 0; table->tp_getattro = 0; table->tp_setattro = 0; // Functions to access object as input/output buffer table->tp_as_buffer = 0; // Flags to define presence of optional/expanded features table->tp_flags = Py_TPFLAGS_DEFAULT; // Documentation string table->tp_doc = 0; table->tp_traverse = 0; // delete references to contained objects table->tp_clear = 0; // Assigned meaning in release 2.1 // rich comparisons table->tp_richcompare = 0; // weak reference enabler table->tp_weaklistoffset = 0; // Iterators table->tp_iter = 0; table->tp_iternext = 0; // Attribute descriptor and subclassing stuff table->tp_methods = 0; table->tp_members = 0; table->tp_getset = 0; table->tp_base = 0; table->tp_dict = 0; table->tp_descr_get = 0; table->tp_descr_set = 0; table->tp_dictoffset = 0; table->tp_init = 0; table->tp_alloc = 0; table->tp_new = 0; table->tp_free = 0; // Low-level free-memory routine table->tp_is_gc = 0; // For PyObject_IS_GC table->tp_bases = 0; table->tp_mro = 0; // method resolution order table->tp_cache = 0; table->tp_subclasses = 0; table->tp_weaklist = 0; table->tp_del = 0; // Type attribute cache version tag. Added in version 2.6 table->tp_version_tag = 0; #ifdef COUNT_ALLOCS table->tp_alloc = 0; table->tp_free = 0; table->tp_maxalloc = 0; table->tp_orev = 0; table->tp_next = 0; #endif } #endif PythonType::~PythonType() { #if defined( Py_LIMITED_API ) delete spec; PyObject_Free( tp_object ); #else delete table; delete sequence_table; delete mapping_table; delete number_table; delete buffer_table; #endif } PyTypeObject *PythonType::type_object() const { #if defined( Py_LIMITED_API ) return tp_object; #else return table; #endif } PythonType &PythonType::name( const char *nam ) { #if defined( Py_LIMITED_API ) spec->name = nam; #else table->tp_name = const_cast( nam ); #endif return *this; } const char *PythonType::getName() const { #if defined( Py_LIMITED_API ) return spec->name; #else return table->tp_name; #endif } PythonType &PythonType::doc( const char *d ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_doc ] = reinterpret_cast( const_cast( d ) ); #else table->tp_doc = const_cast( d ); #endif return *this; } const char *PythonType::getDoc() const { #if defined( Py_LIMITED_API ) if( tp_object ) return reinterpret_cast( PyType_GetSlot( tp_object, Py_tp_doc ) ); std::unordered_map::const_iterator slot = slots.find( Py_tp_doc ); if( slot == slots.end() ) return NULL; return reinterpret_cast( slot->second ); #else return table->tp_doc; #endif } PythonType &PythonType::set_tp_dealloc( void (*tp_dealloc)( PyObject *self ) ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_dealloc ] = reinterpret_cast( tp_dealloc ); #else table->tp_dealloc = tp_dealloc; #endif return *this; } PythonType &PythonType::set_tp_init( int (*tp_init)( PyObject *self, PyObject *args, PyObject *kwds ) ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_init ] = reinterpret_cast( tp_init ); #else table->tp_init = tp_init; #endif return *this; } PythonType &PythonType::set_tp_new( PyObject *(*tp_new)( PyTypeObject *subtype, PyObject *args, PyObject *kwds ) ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_new ] = reinterpret_cast( tp_new ); #else table->tp_new = tp_new; #endif return *this; } PythonType &PythonType::set_methods( PyMethodDef *methods ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_methods ] = reinterpret_cast( methods ); #else table->tp_methods = methods; #endif return *this; } PythonType &PythonType::supportClass() { #if defined( Py_LIMITED_API ) spec->flags |= Py_TPFLAGS_BASETYPE; #else table->tp_flags |= Py_TPFLAGS_BASETYPE; #endif return *this; } #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 PythonType &PythonType::supportPrint() { #if PY_VERSION_HEX < 0x03080000 table->tp_print = print_handler; #endif return *this; } #endif PythonType &PythonType::supportGetattr() { #if defined( Py_LIMITED_API ) slots[ Py_tp_getattr ] = reinterpret_cast( getattr_handler ); #else table->tp_getattr = getattr_handler; #endif return *this; } PythonType &PythonType::supportSetattr() { #if defined( Py_LIMITED_API ) slots[ Py_tp_setattr ] = reinterpret_cast( setattr_handler ); #else table->tp_setattr = setattr_handler; #endif return *this; } PythonType &PythonType::supportGetattro() { #if defined( Py_LIMITED_API ) slots[ Py_tp_getattro ] = reinterpret_cast( getattro_handler ); #else table->tp_getattro = getattro_handler; #endif return *this; } PythonType &PythonType::supportSetattro() { #if defined( Py_LIMITED_API ) slots[ Py_tp_setattro ] = reinterpret_cast( setattro_handler ); #else table->tp_setattro = setattro_handler; #endif return *this; } #ifdef PYCXX_PYTHON_2TO3 PythonType &PythonType::supportCompare( void ) { return *this; } #endif PythonType &PythonType::supportRichCompare() { #if defined( Py_LIMITED_API ) slots[ Py_tp_richcompare ] = reinterpret_cast( rich_compare_handler ); #else table->tp_richcompare = rich_compare_handler; #endif return *this; } PythonType &PythonType::supportRepr() { #if defined( Py_LIMITED_API ) slots[ Py_tp_repr ] = reinterpret_cast( repr_handler ); #else table->tp_repr = repr_handler; #endif return *this; } PythonType &PythonType::supportStr() { #if defined( Py_LIMITED_API ) slots[ Py_tp_str ] = reinterpret_cast( str_handler ); #else table->tp_str = str_handler; #endif return *this; } PythonType &PythonType::supportHash() { #if defined( Py_LIMITED_API ) slots[ Py_tp_hash ] = reinterpret_cast( hash_handler ); #else table->tp_hash = hash_handler; #endif return *this; } PythonType &PythonType::supportCall() { #if defined( Py_LIMITED_API ) slots[ Py_tp_call ] = reinterpret_cast( call_handler ); #else table->tp_call = call_handler; #endif return *this; } PythonType &PythonType::supportIter( int methods_to_support ) { if( methods_to_support&support_iter_iter ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_iter ] = reinterpret_cast( iter_handler ); #else table->tp_iter = iter_handler; #endif } if( methods_to_support&support_iter_iternext ) { #if defined( Py_LIMITED_API ) slots[ Py_tp_iternext ] = reinterpret_cast( iternext_handler ); #else table->tp_iternext = iternext_handler; #endif } return *this; } //-------------------------------------------------------------------------------- // // Handlers // //-------------------------------------------------------------------------------- PythonExtensionBase *getPythonExtensionBase( PyObject *self ) { if(PyType_HasFeature(self->ob_type, Py_TPFLAGS_BASETYPE)) { PythonClassInstance *instance = reinterpret_cast( self ); return instance->m_pycxx_object; } else { return static_cast( self ); } } #if defined( PYCXX_PYTHON_2TO3 ) && !defined ( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 extern "C" int print_handler( PyObject *self, FILE *fp, int flags ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->print( fp, flags ); } catch( BaseException & ) { return -1; // indicate error } } #endif extern "C" PyObject *getattr_handler( PyObject *self, char *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattr( name ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" int setattr_handler( PyObject *self, char *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattr( name, Object( value ) ); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *getattro_handler( PyObject *self, PyObject *name ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->getattro( String( name ) ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" int setattro_handler( PyObject *self, PyObject *name, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->setattro( String( name ), Object( value ) ); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *rich_compare_handler( PyObject *self, PyObject *other, int op ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->rich_compare( Object( other ), op ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *repr_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->repr() ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *str_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->str() ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" Py_hash_t hash_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->hash(); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *call_handler( PyObject *self, PyObject *args, PyObject *kw ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); if( kw != NULL ) return new_reference_to( p->call( Object( args ), Object( kw ) ) ); else return new_reference_to( p->call( Object( args ), Object() ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *iter_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->iter() ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *iternext_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->iternext(); // might be a NULL ptr on end of iteration } catch( BaseException & ) { return NULL; // indicate error } } // Sequence methods extern "C" Py_ssize_t sequence_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_length(); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *sequence_concat_handler( PyObject *self, PyObject *other ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_concat( Object( other ) ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *sequence_repeat_handler( PyObject *self, Py_ssize_t count ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_repeat( count ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *sequence_item_handler( PyObject *self, Py_ssize_t index ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_item( index ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" int sequence_ass_item_handler( PyObject *self, Py_ssize_t index, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_ass_item( index, Object( value ) ); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *sequence_inplace_concat_handler( PyObject *self, PyObject *o2 ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_inplace_concat( Object( o2 ) ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" PyObject *sequence_inplace_repeat_handler( PyObject *self, Py_ssize_t count ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->sequence_inplace_repeat( count ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" int sequence_contains_handler( PyObject *self, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->sequence_contains( Object( value ) ); } catch( BaseException & ) { return -1; // indicate error } } // Mapping extern "C" Py_ssize_t mapping_length_handler( PyObject *self ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_length(); } catch( BaseException & ) { return -1; // indicate error } } extern "C" PyObject *mapping_subscript_handler( PyObject *self, PyObject *key ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return new_reference_to( p->mapping_subscript( Object( key ) ) ); } catch( BaseException & ) { return NULL; // indicate error } } extern "C" int mapping_ass_subscript_handler( PyObject *self, PyObject *key, PyObject *value ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->mapping_ass_subscript( Object( key ), Object( value ) ); } catch( BaseException & ) { return -1; // indicate error } } // Number #define NUMBER_UNARY( slot ) \ extern "C" PyObject *number_ ## slot ## _handler( PyObject *self ) \ { \ try \ { \ PythonExtensionBase *p = getPythonExtensionBase( self ); \ return new_reference_to( p->number_ ## slot() ); \ } \ catch( BaseException & ) \ { \ return NULL; /* indicates error */ \ } \ } #define NUMBER_BINARY( slot ) \ extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other ) \ { \ try \ { \ PythonExtensionBase *p = getPythonExtensionBase( self ); \ return new_reference_to( p->number_ ## slot( Object( other ) ) ); \ } \ catch( BaseException & ) \ { \ return NULL; /* indicates error */ \ } \ } #define NUMBER_TERNARY( slot ) \ extern "C" PyObject *number_ ## slot ## _handler( PyObject *self, PyObject *other1, PyObject *other2 ) \ { \ try \ { \ PythonExtensionBase *p = getPythonExtensionBase( self ); \ return new_reference_to( p->number_ ## slot( Object( other1 ), Object( other2 ) ) ); \ } \ catch( BaseException & ) \ { \ return NULL; /* indicates error */ \ } \ } NUMBER_UNARY( negative ) NUMBER_UNARY( positive ) NUMBER_UNARY( absolute ) NUMBER_UNARY( invert ) NUMBER_UNARY( int ) NUMBER_UNARY( float ) NUMBER_BINARY( add ) NUMBER_BINARY( subtract ) NUMBER_BINARY( multiply ) NUMBER_BINARY( remainder ) NUMBER_BINARY( divmod ) NUMBER_BINARY( lshift ) NUMBER_BINARY( rshift ) NUMBER_BINARY( and ) NUMBER_BINARY( xor ) NUMBER_BINARY( or ) NUMBER_TERNARY( power ) NUMBER_BINARY( floor_divide ) NUMBER_BINARY( true_divide ) NUMBER_UNARY( index ) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 NUMBER_BINARY( matrix_multiply ) #endif NUMBER_BINARY( inplace_add ) NUMBER_BINARY( inplace_subtract ) NUMBER_BINARY( inplace_multiply ) NUMBER_BINARY( inplace_remainder ) NUMBER_TERNARY( inplace_power ) NUMBER_BINARY( inplace_lshift ) NUMBER_BINARY( inplace_rshift ) NUMBER_BINARY( inplace_and ) NUMBER_BINARY( inplace_xor ) NUMBER_BINARY( inplace_or ) NUMBER_BINARY( inplace_floor_divide ) NUMBER_BINARY( inplace_true_divide ) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 NUMBER_BINARY( inplace_matrix_multiply ) #endif #undef NUMBER_UNARY #undef NUMBER_BINARY #undef NUMBER_TERNARY // Buffer #ifndef Py_LIMITED_API extern "C" int buffer_get_handler( PyObject *self, Py_buffer *buf, int flags ) { try { PythonExtensionBase *p = getPythonExtensionBase( self ); return p->buffer_get( buf, flags ); } catch( BaseException & ) { return -1; // indicate error } } extern "C" void buffer_release_handler( PyObject *self, Py_buffer *buf ) { PythonExtensionBase *p = getPythonExtensionBase( self ); p->buffer_release( buf ); // NOTE: No way to indicate error to Python } #endif //================================================================================ // // Implementation of PythonExtensionBase // //================================================================================ #define missing_method( method ) \ throw RuntimeError( "Extension object missing implement of " #method ); PythonExtensionBase::PythonExtensionBase() { ob_refcnt = 0; } PythonExtensionBase::~PythonExtensionBase() { assert( ob_refcnt == 0 ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name ) { TupleN args; return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1 ) { TupleN args( arg1 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2 ) { TupleN args( arg1, arg2 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3 ) { TupleN args( arg1, arg2, arg3 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4 ) { TupleN args( arg1, arg2, arg3, arg4 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5 ) { TupleN args( arg1, arg2, arg3, arg4, arg5 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6 ) { TupleN args( arg1, arg2, arg3, arg4, arg5, arg6 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7 ) { TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8 ) { TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 ); return self().callMemberFunction( fn_name, args ); } Object PythonExtensionBase::callOnSelf( const std::string &fn_name, const Object &arg1, const Object &arg2, const Object &arg3, const Object &arg4, const Object &arg5, const Object &arg6, const Object &arg7, const Object &arg8, const Object &arg9 ) { TupleN args( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ); return self().callMemberFunction( fn_name, args ); } void PythonExtensionBase::reinit( Tuple & /* args */, Dict & /* kwds */) { throw RuntimeError( "Must not call __init__ twice on this class" ); } Object PythonExtensionBase::genericGetAttro( const String &name ) { return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); } int PythonExtensionBase::genericSetAttro( const String &name, const Object &value ) { return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } #if defined( PYCXX_PYTHON_2TO3 ) && !defined( Py_LIMITED_API ) && PY_MINOR_VERSION <= 7 int PythonExtensionBase::print( FILE *, int ) { missing_method( print ); } #endif Object PythonExtensionBase::getattr( const char * ) { missing_method( getattr ); } int PythonExtensionBase::setattr( const char *, const Object & ) { missing_method( setattr ); } Object PythonExtensionBase::getattro( const String &name ) { return asObject( PyObject_GenericGetAttr( selfPtr(), name.ptr() ) ); } int PythonExtensionBase::setattro( const String &name, const Object &value ) { return PyObject_GenericSetAttr( selfPtr(), name.ptr(), value.ptr() ); } int PythonExtensionBase::compare( const Object & ) { missing_method( compare ); } Object PythonExtensionBase::rich_compare( const Object &, int ) { missing_method( rich_compare ); } Object PythonExtensionBase::repr() { missing_method( repr ); } Object PythonExtensionBase::str() { missing_method( str ); } long PythonExtensionBase::hash() { missing_method( hash ); } Object PythonExtensionBase::call( const Object &, const Object & ) { missing_method( call ); } Object PythonExtensionBase::iter() { missing_method( iter ); } PyObject *PythonExtensionBase::iternext() { missing_method( iternext ); } // Sequence methods PyCxx_ssize_t PythonExtensionBase::sequence_length() { missing_method( sequence_length ); } Object PythonExtensionBase::sequence_concat( const Object & ) { missing_method( sequence_concat ); } Object PythonExtensionBase::sequence_repeat( Py_ssize_t ) { missing_method( sequence_repeat ); } Object PythonExtensionBase::sequence_item( Py_ssize_t ) { missing_method( sequence_item ); } int PythonExtensionBase::sequence_ass_item( Py_ssize_t, const Object & ) { missing_method( sequence_ass_item ); } Object PythonExtensionBase::sequence_inplace_concat( const Object & ) { missing_method( sequence_inplace_concat ); } Object PythonExtensionBase::sequence_inplace_repeat( Py_ssize_t ) { missing_method( sequence_inplace_repeat ); } int PythonExtensionBase::sequence_contains( const Object & ) { missing_method( sequence_contains ); } // Mapping PyCxx_ssize_t PythonExtensionBase::mapping_length() { missing_method( mapping_length ); } Object PythonExtensionBase::mapping_subscript( const Object & ) { missing_method( mapping_subscript ); } int PythonExtensionBase::mapping_ass_subscript( const Object &, const Object & ) { missing_method( mapping_ass_subscript ); } // Number #define NUMBER_UNARY( slot ) Object PythonExtensionBase::number_ ## slot() \ { missing_method( number_ ## slot ); } #define NUMBER_BINARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object & ) \ { missing_method( number_ ## slot ); } #define NUMBER_TERNARY( slot ) Object PythonExtensionBase::number_ ## slot( const Object &, const Object & ) \ { missing_method( number_ ## slot ); } NUMBER_UNARY( negative ) NUMBER_UNARY( positive ) NUMBER_UNARY( absolute ) NUMBER_UNARY( invert ) NUMBER_UNARY( int ) NUMBER_UNARY( float ) NUMBER_BINARY( add ) NUMBER_BINARY( subtract ) NUMBER_BINARY( multiply ) NUMBER_BINARY( remainder ) NUMBER_BINARY( divmod ) NUMBER_BINARY( lshift ) NUMBER_BINARY( rshift ) NUMBER_BINARY( and ) NUMBER_BINARY( xor ) NUMBER_BINARY( or ) NUMBER_TERNARY( power ) NUMBER_BINARY( floor_divide ) NUMBER_BINARY( true_divide ) NUMBER_UNARY( index ) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 NUMBER_BINARY( matrix_multiply ) #endif NUMBER_BINARY( inplace_add ) NUMBER_BINARY( inplace_subtract ) NUMBER_BINARY( inplace_multiply ) NUMBER_BINARY( inplace_remainder ) NUMBER_TERNARY( inplace_power ) NUMBER_BINARY( inplace_lshift ) NUMBER_BINARY( inplace_rshift ) NUMBER_BINARY( inplace_and ) NUMBER_BINARY( inplace_xor ) NUMBER_BINARY( inplace_or ) NUMBER_BINARY( inplace_floor_divide ) NUMBER_BINARY( inplace_true_divide ) #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 5 NUMBER_BINARY( inplace_matrix_multiply ) #endif #undef NUMBER_UNARY #undef NUMBER_BINARY #undef NUMBER_TERNARY // Buffer #ifndef Py_LIMITED_API int PythonExtensionBase::buffer_get( Py_buffer * /*buf*/, int /*flags*/ ) { missing_method( buffer_get ); } int PythonExtensionBase::buffer_release( Py_buffer * /*buf*/ ) { // This method is optional and only required if the buffer's // memory is dynamic. return 0; } #endif //-------------------------------------------------------------------------------- // // Method call handlers for // PythonExtensionBase // ExtensionModuleBase // //-------------------------------------------------------------------------------- // Note: Python calls noargs as varargs buts args==NULL extern "C" PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * ) { try { Tuple self_and_name_tuple( _self_and_name_tuple ); PyObject *self_in_cobject = self_and_name_tuple[0].ptr(); void *self_as_void = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Object result( self->invoke_method_noargs( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ) ) ); return new_reference_to( result.ptr() ); } catch( BaseException & ) { 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 = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); Object result ( self->invoke_method_varargs ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args ) ); return new_reference_to( result.ptr() ); } catch( BaseException & ) { return 0; } } 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 = PyCapsule_GetPointer( self_in_cobject, NULL ); if( self_as_void == NULL ) return NULL; ExtensionModuleBase *self = static_cast( self_as_void ); Tuple args( _args ); if( _keywords == NULL ) { Dict keywords; // pass an empty dict Object result ( self->invoke_method_keyword ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args, keywords ) ); return new_reference_to( result.ptr() ); } else { Dict keywords( _keywords ); // make dict Object result ( self->invoke_method_keyword ( PyCapsule_GetPointer( self_and_name_tuple[1].ptr(), NULL ), args, keywords ) ); return new_reference_to( result.ptr() ); } } catch( BaseException & ) { return 0; } } //-------------------------------------------------------------------------------- // // ExtensionExceptionType // //-------------------------------------------------------------------------------- ExtensionExceptionType::ExtensionExceptionType() : 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( module_name.c_str() ), NULL, NULL ), true ); } void ExtensionExceptionType::init( ExtensionModuleBase &module, const std::string& name, ExtensionExceptionType &parent ) { std::string module_name( module.fullName() ); module_name += "."; module_name += name; set( PyErr_NewException( const_cast( module_name.c_str() ), parent.ptr(), NULL ), true ); } ExtensionExceptionType::~ExtensionExceptionType() { } BaseException::BaseException( ExtensionExceptionType &exception, const std::string& reason ) { PyErr_SetString( exception.ptr(), reason.c_str() ); } BaseException::BaseException( ExtensionExceptionType &exception, Object &reason ) { PyErr_SetObject( exception.ptr(), reason.ptr() ); } BaseException::BaseException( PyObject *exception, Object &reason ) { PyErr_SetObject( exception, reason.ptr() ); } BaseException::BaseException( PyObject *exception, const std::string &reason ) { PyErr_SetString( exception, reason.c_str() ); } BaseException::BaseException() { } void BaseException::clear() { PyErr_Clear(); } // is the exception this specific exception 'exc' bool BaseException::matches( ExtensionExceptionType &exc ) { return PyErr_ExceptionMatches( exc.ptr() ) != 0; } Object BaseException::errorType() { PyObject *type, *value, *traceback; PyErr_Fetch( &type, &value, &traceback ); Object result( type ); PyErr_Restore( type, value, traceback ); return result; } Object BaseException::errorValue() { PyObject *type, *value, *traceback; PyErr_Fetch( &type, &value, &traceback ); Object result( value ); PyErr_Restore( type, value, traceback ); return result; } //------------------------------------------------------------ #if 1 //------------------------------------------------------------ // compare operators bool operator!=( const Long &a, const Long &b ) { return a.as_long() != b.as_long(); } bool operator!=( const Long &a, int b ) { return a.as_long() != b; } bool operator!=( const Long &a, long b ) { return a.as_long() != b; } bool operator!=( int a, const Long &b ) { return a != b.as_long(); } bool operator!=( long a, const Long &b ) { return a != b.as_long(); } //------------------------------ bool operator==( const Long &a, const Long &b ) { return a.as_long() == b.as_long(); } bool operator==( const Long &a, int b ) { return a.as_long() == b; } bool operator==( const Long &a, long b ) { return a.as_long() == b; } bool operator==( int a, const Long &b ) { return a == b.as_long(); } bool operator==( long a, const Long &b ) { return a == b.as_long(); } //------------------------------ bool operator>( const Long &a, const Long &b ) { return a.as_long() > b.as_long(); } bool operator>( const Long &a, int b ) { return a.as_long() > b; } bool operator>( const Long &a, long b ) { return a.as_long() > b; } bool operator>( int a, const Long &b ) { return a > b.as_long(); } bool operator>( long a, const Long &b ) { return a > b.as_long(); } //------------------------------ bool operator>=( const Long &a, const Long &b ) { return a.as_long() >= b.as_long(); } bool operator>=( const Long &a, int b ) { return a.as_long() >= b; } bool operator>=( const Long &a, long b ) { return a.as_long() >= b; } bool operator>=( int a, const Long &b ) { return a >= b.as_long(); } bool operator>=( long a, const Long &b ) { return a >= b.as_long(); } //------------------------------ bool operator<( const Long &a, const Long &b ) { return a.as_long() < b.as_long(); } bool operator<( const Long &a, int b ) { return a.as_long() < b; } bool operator<( const Long &a, long b ) { return a.as_long() < b; } bool operator<( int a, const Long &b ) { return a < b.as_long(); } bool operator<( long a, const Long &b ) { return a < b.as_long(); } //------------------------------ bool operator<=( const Long &a, const Long &b ) { return a.as_long() <= b.as_long(); } bool operator<=( int a, const Long &b ) { return a <= b.as_long(); } bool operator<=( long a, const Long &b ) { return a <= b.as_long(); } bool operator<=( const Long &a, int b ) { return a.as_long() <= b; } bool operator<=( const Long &a, long b ) { return a.as_long() <= b; } #ifdef HAVE_LONG_LONG //------------------------------ bool operator!=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() != b; } bool operator!=( PY_LONG_LONG a, const Long &b ) { return a != b.as_long_long(); } //------------------------------ bool operator==( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() == b; } bool operator==( PY_LONG_LONG a, const Long &b ) { return a == b.as_long_long(); } //------------------------------ bool operator>( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() > b; } bool operator>( PY_LONG_LONG a, const Long &b ) { return a > b.as_long_long(); } //------------------------------ bool operator>=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() >= b; } bool operator>=( PY_LONG_LONG a, const Long &b ) { return a >= b.as_long_long(); } //------------------------------ bool operator<( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() < b; } bool operator<( PY_LONG_LONG a, const Long &b ) { return a < b.as_long_long(); } //------------------------------ bool operator<=( const Long &a, PY_LONG_LONG b ) { return a.as_long_long() <= b; } bool operator<=( PY_LONG_LONG a, const Long &b ) { return a <= b.as_long_long(); } #endif #endif //------------------------------------------------------------ // compare operators bool operator!=( const Float &a, const Float &b ) { return a.as_double() != b.as_double(); } bool operator!=( const Float &a, double b ) { return a.as_double() != b; } bool operator!=( double a, const Float &b ) { return a != b.as_double(); } //------------------------------ bool operator==( const Float &a, const Float &b ) { return a.as_double() == b.as_double(); } bool operator==( const Float &a, double b ) { return a.as_double() == b; } bool operator==( double a, const Float &b ) { return a == b.as_double(); } //------------------------------ bool operator>( const Float &a, const Float &b ) { return a.as_double() > b.as_double(); } bool operator>( const Float &a, double b ) { return a.as_double() > b; } bool operator>( double a, const Float &b ) { return a > b.as_double(); } //------------------------------ bool operator>=( const Float &a, const Float &b ) { return a.as_double() >= b.as_double(); } bool operator>=( const Float &a, double b ) { return a.as_double() >= b; } bool operator>=( double a, const Float &b ) { return a >= b.as_double(); } //------------------------------ bool operator<( const Float &a, const Float &b ) { return a.as_double() < b.as_double(); } bool operator<( const Float &a, double b ) { return a.as_double() < b; } bool operator<( double a, const Float &b ) { return a < b.as_double(); } //------------------------------ bool operator<=( const Float &a, const Float &b ) { return a.as_double() <= b.as_double(); } bool operator<=( double a, const Float &b ) { return a <= b.as_double(); } bool operator<=( const Float &a, double b ) { return a.as_double() <= b; } } // end of namespace Py