ConstructorHolder.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: ConstructorHolder.cxx 35499 2010-09-20 23:04:28Z wlav $
00002 // Author: Wim Lavrijsen, Apr 2004
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "ConstructorHolder.h"
00007 #include "Executors.h"
00008 #include "ObjectProxy.h"
00009 #include "MemoryRegulator.h"
00010 #include "Adapters.h"
00011 
00012 // ROOT
00013 #include "TClass.h"
00014 #include "TMethod.h"
00015 
00016 // CINT
00017 #include "Api.h"
00018 
00019 // Standard
00020 #include <string>
00021 
00022 
00023 //- protected members --------------------------------------------------------
00024 template< class T, class M >
00025 Bool_t PyROOT::TConstructorHolder< T, M >::InitExecutor_( TExecutor*& executor )
00026 {
00027 // pick up special case new object executor
00028    executor = (gExecFactories[ "__init__" ])();
00029    return kTRUE;
00030 }
00031 
00032 //- constructors -------------------------------------------------------------
00033 template< class T, class M >
00034 PyROOT::TConstructorHolder< T, M >::TConstructorHolder( const T& klass, const M& method ) :
00035       TMethodHolder< T, M >( klass, method )
00036 {
00037 }
00038 
00039 //____________________________________________________________________________
00040 namespace PyROOT {
00041 
00042 template<>
00043 TConstructorHolder< TScopeAdapter, TMemberAdapter >::TConstructorHolder( const TScopeAdapter& klass ) :
00044    TMethodHolder< TScopeAdapter, TMemberAdapter >( klass, (TFunction*)0 )
00045 {
00046 }
00047 
00048 #ifdef PYROOT_USE_REFLEX
00049 template<>
00050 TConstructorHolder< ROOT::Reflex::Scope, ROOT::Reflex::Member >::TConstructorHolder(
00051       const ROOT::Reflex::Scope& klass ) :
00052    TMethodHolder< ROOT::Reflex::Scope, ROOT::Reflex::Member >( klass, ROOT::Reflex::Member() )
00053 {
00054 }
00055 #endif
00056 
00057 } // namespace PyROOT
00058 
00059 //- public members -----------------------------------------------------------
00060 template< class T, class M >
00061 PyObject* PyROOT::TConstructorHolder< T, M >::GetDocString()
00062 {
00063 // GetMethod() may return an empty function if this is just a special case place holder
00064    std::string clName = this->GetClass().Name();
00065    return PyROOT_PyUnicode_FromFormat( "%s::%s%s",
00066       clName.c_str(), clName.c_str(), this->GetMethod() ? this->GetSignatureString().c_str() : "()" );
00067 }
00068 
00069 //____________________________________________________________________________
00070 namespace PyROOT {
00071 
00072 #ifdef PYROOT_USE_REFLEX
00073 template<>
00074 PyObject* TConstructorHolder< ROOT::Reflex::Scope, ROOT::Reflex::Member >::operator()(
00075       ObjectProxy* self, PyObject* args, PyObject* kwds, Long_t user )
00076 {
00077 // preliminary check in case keywords are accidently used (they are ignored otherwise)
00078    if ( kwds != 0 && PyDict_Size( kwds ) ) {
00079       PyErr_SetString( PyExc_TypeError, "keyword arguments are not yet supported" );
00080       return 0;
00081    }
00082 
00083 // setup as necessary
00084    if ( ! this->Initialize() )
00085       return 0;                              // important: 0, not Py_None
00086 
00087 // fetch self, verify, and put the arguments in usable order
00088    if ( ! ( args = this->FilterArgs( self, args, kwds ) ) )
00089       return 0;
00090 
00091 // translate the arguments
00092    if ( ! this->SetMethodArgs( args, user ) ) {
00093       Py_DECREF( args );
00094       return 0;
00095    }
00096 
00097 // perform the call, and set address if successful
00098    Long_t address = (Long_t)this->Execute( 0 );
00099    if ( address != 0 ) {
00100       Py_INCREF( self );
00101 
00102    // TODO: Fix ownership once ObjectProxy can deal with Reflex
00103       self->Set( (void*)address );
00104 
00105    // done with self
00106       Py_DECREF( self );
00107 
00108       Py_INCREF( Py_None );
00109       return Py_None;                        // by definition
00110    }
00111 
00112    if ( ! PyErr_Occurred() )   // should be set, otherwise write a generic error msg
00113       PyErr_SetString( PyExc_TypeError, const_cast< char* >(
00114          ( this->GetClass().Name() + " constructor failed" ).c_str() ) );
00115 
00116 // do not throw an exception, '0' might trigger the overload handler to choose a
00117 // different constructor, which if all fails will throw an exception
00118    return 0;
00119 }
00120 #endif
00121 
00122 } // namespace PyROOT
00123 
00124 template< class T, class M >
00125 PyObject* PyROOT::TConstructorHolder< T, M >::operator()(
00126       ObjectProxy* self, PyObject* args, PyObject* kwds, Long_t user )
00127 {
00128 // preliminary check in case keywords are accidently used (they are ignored otherwise)
00129    if ( kwds != 0 && PyDict_Size( kwds ) ) {
00130       PyErr_SetString( PyExc_TypeError, "keyword arguments are not yet supported" );
00131       return 0;
00132    }
00133 
00134 // do not allow instantiation of abstract classes
00135    if ( this->GetClass().IsAbstract() ) {
00136       PyErr_Format( PyExc_TypeError,
00137          "%s is abstract and can not be instantiated", this->GetClass().Name().c_str() );
00138       return 0;
00139    }
00140 
00141 // setup as necessary
00142    if ( ! this->Initialize() )
00143       return 0;                              // important: 0, not Py_None
00144 
00145 // fetch self, verify, and put the arguments in usable order
00146    if ( ! ( args = this->FilterArgs( self, args, kwds ) ) )
00147       return 0;
00148 
00149 // translate the arguments
00150    if ( ! this->SetMethodArgs( args, user ) ) {
00151       Py_DECREF( args );
00152       return 0;
00153    }
00154 
00155    TClass* klass = (TClass*)this->GetClass().Id();
00156 
00157 // perform the call (fails for loaded macro's)
00158    Long_t address = (Long_t)this->Execute( klass );
00159    if ( ! address && ( ! PyErr_Occurred() /* exception thrown */ ) ) {
00160    // the ctor call fails for interpreted classes, can deal with limited info, or
00161    // otherwise only deal with default ctor
00162 
00163       if ( klass->GetClassInfo() != 0 ) {
00164          Long_t tagnum = ((G__ClassInfo*)klass->GetClassInfo())->Tagnum();
00165 
00166       // data storage for an object of this class
00167          address = (Long_t)new char[ klass->Size() ];
00168 
00169       // set new globals, while saving current globals
00170          G__StoreEnv env;
00171          G__stubstoreenv( &env, (void*)address, tagnum );
00172 
00173       // build parsable line (gamble that the args look ok when stringyfied, which
00174       // works surprisingly well, as CINT appears to be clairvoyant)
00175          char temp[ G__ONELINE ];
00176          PyObject* str = 0;
00177          std::string fmt = "";
00178          if ( PyTuple_GET_SIZE( args ) == 1 ) {
00179             str = PyObject_Str( PyTuple_GET_ITEM( args, 0 ) );
00180             fmt = "{%s::%s(%s)}";
00181          } else {
00182             str = PyObject_Str( args );
00183             fmt = "{%s::%s%s}";
00184          }
00185 
00186          snprintf( temp, G__ONELINE, fmt.c_str(),
00187             klass->GetName(), klass->GetName(), PyROOT_PyUnicode_AsString( str ) );
00188          Py_DECREF( str );
00189 
00190       // execute contructor
00191          int known = 0;
00192          G__getfunction( temp, &known, G__CALLCONSTRUCTOR );
00193 
00194       // restore original globals
00195          G__stubrestoreenv( &env );
00196 
00197       // in case of failure, the error message will look really, really funky ...
00198 
00199       // CAUTION: creating an interpreted class doesn't work if it has STL type data
00200       // members that are initialized or otherwise touched in the ctor!
00201 
00202       } else if ( PyTuple_GET_SIZE( args ) == 0 ) {
00203       // unknown class, but can still create placeholder if size is known
00204          address = (Long_t)klass->New();
00205       }
00206    }
00207 
00208 // done with filtered args
00209    Py_DECREF( args );
00210 
00211 // return object if successful, lament if not
00212    if ( address != 0 ) {
00213       Py_INCREF( self );
00214 
00215    // note: constructors are no longer set to take ownership by default; instead that is
00216    // decided by the method proxy (which carries a creator flag) upon return
00217       self->Set( (void*)address );
00218 
00219    // allow lookup upon destruction on the ROOT/CINT side for TObjects
00220       TObject* object = (TObject*) klass->DynamicCast( TObject::Class(), (void*)address );
00221       if ( object )
00222          TMemoryRegulator::RegisterObject( self, object );
00223 
00224    // done with self
00225       Py_DECREF( self );
00226 
00227       Py_INCREF( Py_None );
00228       return Py_None;                        // by definition
00229    }
00230 
00231    if ( ! PyErr_Occurred() )   // should be set, otherwise write a generic error msg
00232       PyErr_SetString( PyExc_TypeError, const_cast< char* >(
00233          ( std::string( klass->GetName() ) + " constructor failed" ).c_str() ) );
00234 
00235 // do not throw an exception, '0' might trigger the overload handler to choose a
00236 // different constructor, which if all fails will throw an exception
00237    return 0;
00238 }
00239 
00240 //____________________________________________________________________________
00241 template class PyROOT::TConstructorHolder< PyROOT::TScopeAdapter, PyROOT::TMemberAdapter >;
00242 #ifdef PYROOT_USE_REFLEX
00243 template class PyROOT::TConstructorHolder< ROOT::Reflex::Scope, ROOT::Reflex::Member >;
00244 #endif

Generated on Tue Jul 5 14:10:11 2011 for ROOT_528-00b_version by  doxygen 1.5.1