ExtensionOldType.hxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------------------------
00002 //
00003 // Copyright (c) 1998 - 2007, The Regents of the University of California
00004 // Produced at the Lawrence Livermore National Laboratory
00005 // All rights reserved.
00006 //
00007 // This file is part of PyCXX. For details,see http://cxx.sourceforge.net/. The
00008 // full copyright notice is contained in the file COPYRIGHT located at the root
00009 // of the PyCXX distribution.
00010 //
00011 // Redistribution  and  use  in  source  and  binary  forms,  with  or  without
00012 // modification, are permitted provided that the following conditions are met:
00013 //
00014 //  - Redistributions of  source code must  retain the above  copyright notice,
00015 //    this list of conditions and the disclaimer below.
00016 //  - Redistributions in binary form must reproduce the above copyright notice,
00017 //    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
00018 //    documentation and/or materials provided with the distribution.
00019 //  - Neither the name of the UC/LLNL nor  the names of its contributors may be
00020 //    used to  endorse or  promote products derived from  this software without
00021 //    specific prior written permission.
00022 //
00023 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
00024 // AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
00025 // IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
00026 // ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
00027 // CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
00028 // ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
00029 // DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
00030 // SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
00031 // CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
00032 // LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
00033 // OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00034 // DAMAGE.
00035 //
00036 //-----------------------------------------------------------------------------
00037 
00038 #ifndef __CXX_ExtensionOldType__h
00039 #define __CXX_ExtensionOldType__h
00040 
00041 namespace Py
00042 {
00043     template<TEMPLATE_TYPENAME T> class PythonExtension
00044     : public PythonExtensionBase
00045     {
00046     public:
00047         static PyTypeObject *type_object()
00048         {
00049             return behaviors().type_object();
00050         }
00051 
00052         static bool check( PyObject *p )
00053         {
00054             // is p like me?
00055             return p->ob_type == type_object();
00056         }
00057 
00058         static bool check( const Object &ob )
00059         {
00060             return check( ob.ptr() );
00061         }
00062 
00063         //
00064         // every object needs getattr implemented
00065         // to support methods
00066         //
00067         virtual Object getattr( const char *name )
00068         {
00069             return getattr_methods( name );
00070         }
00071 
00072         PyObject *selfPtr()
00073         {
00074             return this;
00075         }
00076 
00077         Object self()
00078         {
00079             return asObject( this );
00080         }
00081 
00082     protected:
00083         explicit PythonExtension()
00084         : PythonExtensionBase()
00085         {
00086             PyObject_Init( this, type_object() );
00087 
00088             // every object must support getattr
00089             behaviors().supportGetattr();
00090         }
00091 
00092         virtual ~PythonExtension()
00093         {}
00094 
00095         static PythonType &behaviors()
00096         {
00097             static PythonType* p;
00098             if( p == NULL )
00099             {
00100 #if defined( _CPPRTTI ) || defined( __GNUG__ )
00101                 const char *default_name =( typeid( T ) ).name();
00102 #else
00103                 const char *default_name = "unknown";
00104 #endif
00105                 p = new PythonType( sizeof( T ), 0, default_name );
00106                 p->set_tp_dealloc( extension_object_deallocator );
00107             }
00108 
00109             return *p;
00110         }
00111 
00112         typedef Object (T::*method_noargs_function_t)();
00113         typedef Object (T::*method_varargs_function_t)( const Tuple &args );
00114         typedef Object (T::*method_keyword_function_t)( const Tuple &args, const Dict &kws );
00115         typedef std::map<std::string, MethodDefExt<T> *> method_map_t;
00116 
00117         // support the default attributes, __name__, __doc__ and methods
00118         virtual Object getattr_default( const char *_name )
00119         {
00120             std::string name( _name );
00121 
00122             if( name == "__name__" && type_object()->tp_name != NULL )
00123             {
00124                 return Py::String( type_object()->tp_name );
00125             }
00126 
00127             if( name == "__doc__" && type_object()->tp_doc != NULL )
00128             {
00129                 return Py::String( type_object()->tp_doc );
00130             }
00131 
00132 // trying to fake out being a class for help()
00133 //            else if( name == "__bases__"  )
00134 //            {
00135 //                return Py::Tuple( 0 );
00136 //            }
00137 //            else if( name == "__module__"  )
00138 //            {
00139 //                return Py::Nothing();
00140 //            }
00141 //            else if( name == "__dict__"  )
00142 //            {
00143 //                return Py::Dict();
00144 //            }
00145 
00146             return getattr_methods( _name );
00147         }
00148 
00149         // turn a name into function object
00150         virtual Object getattr_methods( const char *_name )
00151         {
00152             std::string name( _name );
00153 
00154             method_map_t &mm = methods();
00155 
00156             // see if name exists and get entry with method
00157             EXPLICIT_TYPENAME method_map_t::const_iterator i = mm.find( name );
00158             if( i == mm.end() )
00159             {
00160                 if( name == "__methods__" )
00161                 {
00162                     List methods;
00163 
00164                     i = mm.begin();
00165                     EXPLICIT_TYPENAME method_map_t::const_iterator i_end = mm.end();
00166 
00167                     for( ; i != i_end; ++i )
00168                         methods.append( String( (*i).first ) );
00169 
00170                     return methods;
00171                 }
00172 
00173                 throw AttributeError( name );
00174             }
00175 
00176             MethodDefExt<T> *method_def = i->second;
00177 
00178             Tuple self( 2 );
00179 
00180             self[0] = Object( this );
00181             self[1] = Object( PyCObject_FromVoidPtr( method_def, do_not_dealloc ) );
00182 
00183             PyObject *func = PyCFunction_New( &method_def->ext_meth_def, self.ptr() );
00184 
00185             return Object(func, true);
00186         }
00187 
00188         // check that all methods added are unique
00189         static void check_unique_method_name( const char *name )
00190         {
00191             method_map_t &mm = methods();
00192             EXPLICIT_TYPENAME method_map_t::const_iterator i;
00193             i = mm.find( name );
00194             if( i != mm.end() )
00195                 throw AttributeError( name );
00196         }
00197 
00198         static void add_noargs_method( const char *name, method_noargs_function_t function, const char *doc="" )
00199         {
00200             check_unique_method_name( name );
00201             method_map_t &mm = methods();
00202             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_noargs_call_handler, doc );
00203         }
00204 
00205         static void add_varargs_method( const char *name, method_varargs_function_t function, const char *doc="" )
00206         {
00207             check_unique_method_name( name );
00208             method_map_t &mm = methods();
00209             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_varargs_call_handler, doc );
00210         }
00211 
00212         static void add_keyword_method( const char *name, method_keyword_function_t function, const char *doc="" )
00213         {
00214             check_unique_method_name( name );
00215             method_map_t &mm = methods();
00216             mm[ std::string( name ) ] = new MethodDefExt<T>( name, function, method_keyword_call_handler, doc );
00217         }
00218 
00219     private:
00220         static method_map_t &methods( void )
00221         {
00222             static method_map_t *map_of_methods = NULL;
00223             if( map_of_methods == NULL )
00224                 map_of_methods = new method_map_t;
00225 
00226             return *map_of_methods;
00227         }
00228 
00229         // Note: Python calls noargs as varargs buts args==NULL
00230         static PyObject *method_noargs_call_handler( PyObject *_self_and_name_tuple, PyObject * )
00231         {
00232             try
00233             {
00234                 Tuple self_and_name_tuple( _self_and_name_tuple );
00235 
00236                 PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
00237                 T *self = static_cast<T *>( self_in_cobject );
00238                 MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
00239                                                 PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
00240                 Object result;
00241 
00242                 // Adding try & catch in case of STL debug-mode exceptions.
00243                 #ifdef _STLP_DEBUG
00244                 try
00245                 {
00246                     result = (self->*meth_def->ext_noargs_function)();
00247                 }
00248                 catch( std::__stl_debug_exception )
00249                 {
00250                     // throw cxx::RuntimeError( sErrMsg );
00251                     throw RuntimeError( "Error message not set yet." );
00252                 }
00253                 #else
00254                 result = (self->*meth_def->ext_noargs_function)();
00255                 #endif // _STLP_DEBUG
00256 
00257                 return new_reference_to( result.ptr() );
00258             }
00259             catch( Exception & )
00260             {
00261                 return 0;
00262             }
00263         }
00264 
00265         static PyObject *method_varargs_call_handler( PyObject *_self_and_name_tuple, PyObject *_args )
00266         {
00267             try
00268             {
00269                 Tuple self_and_name_tuple( _self_and_name_tuple );
00270 
00271                 PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
00272                 T *self = static_cast<T *>( self_in_cobject );
00273 
00274                 MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
00275                                                 PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
00276                 Tuple args( _args );
00277 
00278                 Object result;
00279 
00280                 // Adding try & catch in case of STL debug-mode exceptions.
00281                 #ifdef _STLP_DEBUG
00282                 try
00283                 {
00284                     result = (self->*meth_def->ext_varargs_function)( args );
00285                 }
00286                 catch( std::__stl_debug_exception )
00287                 {
00288                     throw RuntimeError( "Error message not set yet." );
00289                 }
00290                 #else
00291                 result = (self->*meth_def->ext_varargs_function)( args );
00292                 #endif // _STLP_DEBUG
00293 
00294                 return new_reference_to( result.ptr() );
00295             }
00296             catch( Exception & )
00297             {
00298                 return 0;
00299             }
00300         }
00301 
00302         static PyObject *method_keyword_call_handler( PyObject *_self_and_name_tuple, PyObject *_args, PyObject *_keywords )
00303         {
00304             try
00305             {
00306                 Tuple self_and_name_tuple( _self_and_name_tuple );
00307 
00308                 PyObject *self_in_cobject = self_and_name_tuple[0].ptr();
00309                 T *self = static_cast<T *>( self_in_cobject );
00310 
00311                 MethodDefExt<T> *meth_def = reinterpret_cast<MethodDefExt<T> *>(
00312                                                 PyCObject_AsVoidPtr( self_and_name_tuple[1].ptr() ) );
00313 
00314                 Tuple args( _args );
00315 
00316                 // _keywords may be NULL so be careful about the way the dict is created
00317                 Dict keywords;
00318                 if( _keywords != NULL )
00319                     keywords = Dict( _keywords );
00320 
00321                 Object result( ( self->*meth_def->ext_keyword_function )( args, keywords ) );
00322 
00323                 return new_reference_to( result.ptr() );
00324             }
00325             catch( Exception & )
00326             {
00327                 return 0;
00328             }
00329         }
00330 
00331         static void extension_object_deallocator( PyObject* t )
00332         {
00333             delete (T *)( t );
00334         }
00335 
00336         //
00337         // prevent the compiler generating these unwanted functions
00338         //
00339         explicit PythonExtension( const PythonExtension<T> &other );
00340         void operator=( const PythonExtension<T> &rhs );
00341     };
00342 
00343     //
00344     // ExtensionObject<T> is an Object that will accept only T's.
00345     //
00346     template<TEMPLATE_TYPENAME T>
00347     class ExtensionObject: public Object
00348     {
00349     public:
00350 
00351         explicit ExtensionObject( PyObject *pyob )
00352         : Object( pyob )
00353         {
00354             validate();
00355         }
00356 
00357         ExtensionObject( const ExtensionObject<T> &other )
00358         : Object( *other )
00359         {
00360             validate();
00361         }
00362 
00363         ExtensionObject( const Object &other )
00364         : Object( *other )
00365         {
00366             validate();
00367         }
00368 
00369         ExtensionObject &operator=( const Object &rhs )
00370         {
00371             return( *this = *rhs );
00372         }
00373 
00374         ExtensionObject &operator=( PyObject *rhsp )
00375         {
00376             if( ptr() != rhsp )
00377                 set( rhsp );
00378             return *this;
00379         }
00380 
00381         virtual bool accepts( PyObject *pyob ) const
00382         {
00383             return( pyob && T::check( pyob ) );
00384         }
00385 
00386         //
00387         //    Obtain a pointer to the PythonExtension object
00388         //
00389         T *extensionObject( void )
00390         {
00391             return static_cast<T *>( ptr() );
00392         }
00393     };
00394 } // Namespace Py
00395 
00396 // End of __CXX_ExtensionOldType__h
00397 #endif

Generated on Wed Nov 23 19:00:10 2011 for FreeCAD by  doxygen 1.6.1