00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef __CXX_ExtensionClass__h
00039 #define __CXX_ExtensionClass__h
00040
00041 #define PYCXX_NOARGS_METHOD_NAME( NAME ) _callNoArgsMethod__##NAME
00042 #define PYCXX_VARARGS_METHOD_NAME( NAME ) _callVarArgsMethod__##NAME
00043 #define PYCXX_KEYWORDS_METHOD_NAME( NAME ) _callKeywordsMethod__##NAME
00044
00045 #define PYCXX_NOARGS_METHOD_DECL( CLS, NAME ) \
00046 static PyObject *PYCXX_NOARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *, PyObject * ) \
00047 { \
00048 try \
00049 { \
00050 Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
00051 CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
00052 Py::Object r( (self->NAME)() ); \
00053 return Py::new_reference_to( r.ptr() ); \
00054 } \
00055 catch( Py::Exception & ) \
00056 { \
00057 return 0; \
00058 } \
00059 }
00060 #define PYCXX_VARARGS_METHOD_DECL( CLS, NAME ) \
00061 static PyObject *PYCXX_VARARGS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject * ) \
00062 { \
00063 try \
00064 { \
00065 Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
00066 CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
00067 Py::Tuple a( _a ); \
00068 Py::Object r( (self->NAME)( a ) ); \
00069 return Py::new_reference_to( r.ptr() ); \
00070 } \
00071 catch( Py::Exception & ) \
00072 { \
00073 return 0; \
00074 } \
00075 }
00076 #define PYCXX_KEYWORDS_METHOD_DECL( CLS, NAME ) \
00077 static PyObject *PYCXX_KEYWORDS_METHOD_NAME( NAME )( PyObject *_self, PyObject *_a, PyObject *_k ) \
00078 { \
00079 try \
00080 { \
00081 Py::PythonClassInstance *self_python = reinterpret_cast< Py::PythonClassInstance * >( _self ); \
00082 CLS *self = reinterpret_cast< CLS * >( self_python->m_pycxx_object ); \
00083 Py::Tuple a( _a ); \
00084 Py::Dict k; \
00085 if( _k != NULL ) \
00086 k = _k; \
00087 Py::Object r( (self->NAME)( a, k ) ); \
00088 return Py::new_reference_to( r.ptr() ); \
00089 } \
00090 catch( Py::Exception & ) \
00091 { \
00092 return 0; \
00093 } \
00094 }
00095
00096
00097
00098 #define PYCXX_ADD_NOARGS_METHOD( PYNAME, NAME, docs ) \
00099 add_method( #PYNAME, (PyCFunction)PYCXX_NOARGS_METHOD_NAME( NAME ), METH_NOARGS, docs )
00100 #define PYCXX_ADD_VARARGS_METHOD( PYNAME, NAME, docs ) \
00101 add_method( #PYNAME, (PyCFunction)PYCXX_VARARGS_METHOD_NAME( NAME ), METH_VARARGS, docs )
00102 #define PYCXX_ADD_KEYWORDS_METHOD( PYNAME, NAME, docs ) \
00103 add_method( #PYNAME, (PyCFunction)PYCXX_KEYWORDS_METHOD_NAME( NAME ), METH_VARARGS | METH_KEYWORDS, docs )
00104
00105 namespace Py
00106 {
00107 extern PythonExtensionBase *getPythonExtensionBase( PyObject *self );
00108
00109 struct PythonClassInstance
00110 {
00111 PyObject_HEAD
00112 PythonExtensionBase *m_pycxx_object;
00113 };
00114
00115
00116 class PYCXX_EXPORT ExtensionClassMethodsTable
00117 {
00118 public:
00119 ExtensionClassMethodsTable()
00120 : m_methods_table( new PyMethodDef[ METHOD_TABLE_SIZE_INCREMENT ] )
00121 , m_methods_used( 0 )
00122 , m_methods_size( METHOD_TABLE_SIZE_INCREMENT )
00123 {
00124 }
00125
00126 ~ExtensionClassMethodsTable()
00127 {
00128 delete m_methods_table;
00129 }
00130
00131
00132 void check_unique_method_name( const char *_name )
00133 {
00134 std::string name( _name );
00135 for( int i=0; i<m_methods_used; i++ )
00136 {
00137 if( name == m_methods_table[i].ml_name )
00138 {
00139 throw AttributeError( name );
00140 }
00141 }
00142 }
00143 PyMethodDef *add_method( const char *name, PyCFunction function, int flags, const char *doc )
00144 {
00145 check_unique_method_name( name );
00146
00147
00148 if( m_methods_used == (m_methods_size-1) )
00149 {
00150 PyMethodDef *old_mt = m_methods_table;
00151 m_methods_size += METHOD_TABLE_SIZE_INCREMENT;
00152 PyMethodDef *new_mt = new PyMethodDef[ m_methods_size ];
00153 for( int i=0; i<m_methods_used; i++ )
00154 {
00155 new_mt[ i ] = old_mt[ i ];
00156 }
00157 delete[] old_mt;
00158 m_methods_table = new_mt;
00159 }
00160
00161
00162 PyMethodDef *p = &m_methods_table[ m_methods_used ];
00163 p->ml_name = const_cast<char *>( name );
00164 p->ml_meth = function;
00165 p->ml_flags = flags;
00166 p->ml_doc = const_cast<char *>( doc );
00167
00168 m_methods_used++;
00169 p++;
00170
00171
00172 p->ml_name = NULL;
00173 p->ml_meth = NULL;
00174 p->ml_flags = 0;
00175 p->ml_doc = NULL;
00176
00177 return m_methods_table;
00178 }
00179
00180 private:
00181 enum {METHOD_TABLE_SIZE_INCREMENT = 1};
00182 PyMethodDef *m_methods_table;
00183 int m_methods_used;
00184 int m_methods_size;
00185 };
00186
00187 template<TEMPLATE_TYPENAME T> class PythonClass
00188 : public PythonExtensionBase
00189 {
00190 protected:
00191 explicit PythonClass( PythonClassInstance *self, Tuple &args, Dict &kwds )
00192 : PythonExtensionBase()
00193 , m_class_instance( self )
00194 {
00195 }
00196
00197 virtual ~PythonClass()
00198 {}
00199
00200 static ExtensionClassMethodsTable &methodTable()
00201 {
00202 static ExtensionClassMethodsTable *method_table;
00203 if( method_table == NULL )
00204 method_table = new ExtensionClassMethodsTable;
00205 return *method_table;
00206 }
00207
00208 static void add_method( const char *name, PyCFunction function, int flags, const char *doc=NULL )
00209 {
00210 behaviors().set_methods( methodTable().add_method( name, function, flags, doc ) );
00211 }
00212
00213 static PythonType &behaviors()
00214 {
00215 static PythonType *p;
00216 if( p == NULL )
00217 {
00218 #if defined( _CPPRTTI ) || defined( __GNUG__ )
00219 const char *default_name = (typeid( T )).name();
00220 #else
00221 const char *default_name = "unknown";
00222 #endif
00223 p = new PythonType( sizeof( T ), 0, default_name );
00224 p->set_tp_new( extension_object_new );
00225 p->set_tp_init( extension_object_init );
00226 p->set_tp_dealloc( extension_object_deallocator );
00227
00228 p->supportClass();
00229
00230
00231 p->supportGetattro();
00232 p->supportSetattro();
00233 }
00234
00235 return *p;
00236 }
00237
00238 static PyObject *extension_object_new( PyTypeObject *subtype, PyObject *args, PyObject *kwds )
00239 {
00240 #ifdef PYCXX_DEBUG
00241 std::cout << "extension_object_new()" << std::endl;
00242 #endif
00243 PythonClassInstance *o = reinterpret_cast<PythonClassInstance *>( subtype->tp_alloc( subtype, 0 ) );
00244 if( o == NULL )
00245 return NULL;
00246
00247 o->m_pycxx_object = NULL;
00248
00249 PyObject *self = reinterpret_cast<PyObject *>( o );
00250 #ifdef PYCXX_DEBUG
00251 std::cout << "extension_object_new() => self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << std::endl;
00252 #endif
00253 return self;
00254 }
00255
00256 static int extension_object_init( PyObject *_self, PyObject *args_, PyObject *kwds_ )
00257 {
00258 try
00259 {
00260 Py::Tuple args( args_ );
00261 Py::Dict kwds;
00262 if( kwds_ != NULL )
00263 kwds = kwds_;
00264
00265 PythonClassInstance *self = reinterpret_cast<PythonClassInstance *>( _self );
00266 #ifdef PYCXX_DEBUG
00267 std::cout << "extension_object_init( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
00268 std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
00269 #endif
00270
00271 if( self->m_pycxx_object == NULL )
00272 {
00273 self->m_pycxx_object = new T( self, args, kwds );
00274 #ifdef PYCXX_DEBUG
00275 std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
00276 #endif
00277 }
00278 else
00279 {
00280 #ifdef PYCXX_DEBUG
00281 std::cout << " reinit - self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
00282 #endif
00283 self->m_pycxx_object->reinit( args, kwds );
00284 }
00285 }
00286 catch( Exception & )
00287 {
00288 return -1;
00289 }
00290 return 0;
00291 }
00292
00293 static void extension_object_deallocator( PyObject *_self )
00294 {
00295 PythonClassInstance *self = reinterpret_cast< PythonClassInstance * >( _self );
00296 #ifdef PYCXX_DEBUG
00297 std::cout << "extension_object_deallocator( self=0x" << std::hex << reinterpret_cast< unsigned int >( self ) << std::dec << " )" << std::endl;
00298 std::cout << " self->m_pycxx_object=0x" << std::hex << reinterpret_cast< unsigned int >( self->m_pycxx_object ) << std::dec << std::endl;
00299 #endif
00300 delete self->m_pycxx_object;
00301 _self->ob_type->tp_free( _self );
00302 }
00303
00304 public:
00305 static PyTypeObject *type_object()
00306 {
00307 return behaviors().type_object();
00308 }
00309
00310 static Object type()
00311 {
00312 return Object( reinterpret_cast<PyObject *>( behaviors().type_object() ) );
00313 }
00314
00315 static bool check( PyObject *p )
00316 {
00317
00318 return p->ob_type == type_object();
00319 }
00320
00321 static bool check( const Object &ob )
00322 {
00323 return check( ob.ptr() );
00324 }
00325
00326 virtual PyObject *selfPtr()
00327 {
00328 return reinterpret_cast<PyObject *>( m_class_instance );
00329 }
00330
00331 virtual Object self()
00332 {
00333 return Object( reinterpret_cast<PyObject *>( m_class_instance ) );
00334 }
00335
00336 protected:
00337 private:
00338 PythonClassInstance *m_class_instance;
00339
00340 private:
00341
00342
00343
00344 explicit PythonClass( const PythonClass<T> &other );
00345 void operator=( const PythonClass<T> &rhs );
00346 };
00347
00348
00349
00350
00351 template<TEMPLATE_TYPENAME T>
00352 class PythonClassObject: public Object
00353 {
00354 public:
00355
00356 explicit PythonClassObject( PyObject *pyob )
00357 : Object( pyob )
00358 {
00359 validate();
00360 }
00361
00362 PythonClassObject( const PythonClassObject<T> &other )
00363 : Object( *other )
00364 {
00365 validate();
00366 }
00367
00368 PythonClassObject( const Object &other )
00369 : Object( *other )
00370 {
00371 validate();
00372 }
00373
00374 PythonClassObject &operator=( const Object &rhs )
00375 {
00376 *this = *rhs;
00377 return *this;
00378 }
00379
00380 PythonClassObject &operator=( PyObject *rhsp )
00381 {
00382 if( ptr() != rhsp )
00383 set( rhsp );
00384 return *this;
00385 }
00386
00387 virtual bool accepts( PyObject *pyob ) const
00388 {
00389 return( pyob && T::check( pyob ) );
00390 }
00391
00392
00393
00394
00395 T *getCxxObject( void )
00396 {
00397 return dynamic_cast< T * >( getPythonExtensionBase( ptr() ) );
00398 }
00399 };
00400 }
00401
00402
00403 #endif