TPyClassGenerator.cxx

Go to the documentation of this file.
00001 // @(#)root/pyroot:$Id: TPyClassGenerator.cxx 35499 2010-09-20 23:04:28Z wlav $
00002 // Author: Wim Lavrijsen, May 2004
00003 
00004 // Bindings
00005 #include "PyROOT.h"
00006 #include "TPyClassGenerator.h"
00007 #include "Utility.h"
00008 #include "TPyReturn.h"
00009 
00010 // ROOT
00011 #include "TClass.h"
00012 
00013 // CINT
00014 #include "Api.h"
00015 
00016 // Standard
00017 #include <string>
00018 #include <typeinfo>
00019 
00020 
00021 //- private helpers ----------------------------------------------------------
00022 namespace {
00023 
00024    //_________________________________________________________________________
00025    int PyCtorCallback( G__value* res, G__CONST char*, struct G__param* /* libp */, int /* hash */ )
00026    {
00027       PyObject* pyclass = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) );
00028       if ( ! pyclass )
00029          return 0;
00030 
00031       PyObject* args = PyTuple_New( 0 );
00032       PyObject* result = PyObject_Call( pyclass, args, NULL );
00033       if ( ! result )
00034          PyErr_Print();
00035       Py_DECREF( args );
00036 
00037       G__letint( res, 'u', (Long_t)result );
00038       res->ref = (Long_t)result;
00039 
00040       G__linked_taginfo pti;
00041       pti.tagnum = -1;
00042       pti.tagtype = 'c';
00043 
00044       PyObject* str = PyObject_Str( pyclass );
00045       std::string clName = PyROOT_PyUnicode_AsString( str );
00046       Py_DECREF( str );
00047 
00048       clName = clName.substr( clName.rfind( '.' )+1, std::string::npos );
00049       pti.tagname = clName.c_str();
00050 
00051       G__set_tagnum( res, G__get_linked_tagnum( &pti ) );
00052 
00053       return ( 1 );
00054    }
00055 
00056    //_________________________________________________________________________
00057    int PyMemFuncCallback( G__value* res, G__CONST char*, struct G__param* libp, int /* hash */)
00058    {
00059       PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) );
00060       if ( ! pyfunc )
00061          return 0;
00062 
00063       PyObject* self = (PyObject*)G__getstructoffset();
00064       Py_INCREF( self );
00065 
00066       PyObject* args = PyTuple_New( 1 + libp->paran );
00067       PyTuple_SetItem( args, 0, self );
00068       for ( int i = 0; i < libp->paran; ++i ) {
00069          PyObject* arg = 0;
00070          switch ( G__value_get_type(&libp->para[i]) ) {
00071          case 'd':
00072             arg = PyFloat_FromDouble( G__Mdouble(libp->para[i]) );
00073             break;
00074          case 'f':
00075             arg = PyFloat_FromDouble( (double)G__Mfloat(libp->para[i]) );
00076             break;
00077          case 'l':
00078             arg = PyLong_FromLong( G__Mlong(libp->para[i]) );
00079             break;
00080          case 'k':
00081             arg = PyLong_FromUnsignedLong( G__Mulong(libp->para[i] ) );
00082             break;
00083          case 'i':
00084             arg = PyInt_FromLong( (Long_t)G__Mint(libp->para[i]) );
00085             break;
00086          case 'h':
00087             //arg = PyLong_FromUnsignedLong( (UInt_t)G__Muint(libp->para[i]) );
00088             arg = PyLong_FromUnsignedLong( *(ULong_t*)((void*)G__Mlong(libp->para[i])) );
00089             break;
00090          case 's':
00091             arg = PyInt_FromLong( (Long_t)G__Mshort(libp->para[i]) );
00092             break;
00093          case 'r':
00094             arg = PyInt_FromLong( (Long_t)G__Mushort(libp->para[i]) );
00095             break;
00096          case 'u':
00097          // longlong, ulonglong, longdouble
00098             break;
00099          case 'c':
00100             char cc[2]; cc[0] = G__Mchar(libp->para[i]); cc[1] = '\0';
00101             arg = PyBytes_FromString( cc );
00102             break;
00103          case 'b':
00104          // unsigned char
00105             break;
00106          case 'C':
00107             arg = PyBytes_FromString( (char*)G__Mlong(libp->para[i]) );
00108             break;
00109          }
00110 
00111          if ( arg != 0 )
00112             PyTuple_SetItem( args, i+1, arg );         // steals ref to arg
00113          else {
00114             PyErr_Format( PyExc_TypeError,
00115                "error converting parameter: %d (type: %c)", i, G__value_get_type(&libp->para[i]) );
00116             break;
00117          }
00118 
00119       }
00120 
00121       PyObject* result = 0;
00122       if ( ! PyErr_Occurred() )
00123          result =  PyObject_Call( pyfunc, args, NULL );
00124       Py_DECREF( args );
00125 
00126       if ( ! result )
00127          PyErr_Print();
00128 
00129       TPyReturn* retval = new TPyReturn( result );
00130       G__letint( res, 'u', (Long_t)retval );
00131       res->ref = (Long_t)retval;
00132       G__set_tagnum( res, ((G__ClassInfo*)TPyReturn::Class()->GetClassInfo())->Tagnum() );
00133 
00134       return ( 1 );
00135    }
00136 
00137 } // unnamed namespace
00138 
00139 
00140 //- public members -----------------------------------------------------------
00141 TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load )
00142 {
00143    return GetClass( name, load, kFALSE );
00144 }
00145 
00146 //- public members -----------------------------------------------------------
00147 TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silent )
00148 {
00149    // called if all other class generators failed, attempt to build from python class
00150    if ( PyROOT::gDictLookupActive == kTRUE )
00151       return 0;                              // call originated from python
00152 
00153    if ( ! load || ! name )
00154       return 0;
00155 
00156 // determine module and class name part
00157    std::string clName = name;
00158    std::string::size_type pos = clName.rfind( '.' );
00159 
00160    if ( pos == std::string::npos )
00161       return 0;                              // this isn't a python style class
00162    
00163    std::string mdName = clName.substr( 0, pos );
00164    clName = clName.substr( pos+1, std::string::npos );
00165 
00166 // ROOT doesn't know about python modules; the class may exist (TODO: add scopes)
00167    if ( TClass::GetClass( clName.c_str(), load, silent ) )
00168       return TClass::GetClass( clName.c_str(), load, silent );
00169 
00170 // locate and get class
00171    PyObject* mod = PyImport_AddModule( const_cast< char* >( mdName.c_str() ) );
00172    if ( ! mod ) {
00173       PyErr_Clear();
00174       return 0;                              // module apparently disappeared
00175    }
00176 
00177    Py_INCREF( mod );
00178    PyObject* pyclass =
00179       PyDict_GetItemString( PyModule_GetDict( mod ), const_cast< char* >( clName.c_str() ) );
00180    Py_XINCREF( pyclass );
00181    Py_DECREF( mod );
00182 
00183    if ( ! pyclass ) {
00184       PyErr_Clear();                         // the class is no longer available?!
00185       return 0;
00186    }
00187 
00188 // get a listing of all python-side members
00189    PyObject* attrs = PyObject_Dir( pyclass );
00190    if ( ! attrs ) {
00191       PyErr_Clear();
00192       Py_DECREF( pyclass );
00193       return 0;
00194    }
00195 
00196 // build CINT class placeholder
00197    G__linked_taginfo pti;
00198    pti.tagnum = -1;
00199    pti.tagtype = 'c';
00200    pti.tagname = clName.c_str();
00201    G__add_compiledheader( (clName+".h").c_str() );
00202 
00203    int tagnum = G__get_linked_tagnum( &pti );
00204 
00205    G__tagtable_setup(
00206       tagnum, sizeof(PyObject), G__CPPLINK, 0x00020000, "", 0, 0 );
00207 
00208    G__ClassInfo gcl( tagnum );
00209 
00210    G__tag_memfunc_setup( tagnum );
00211 
00212 // special case: constructor; add method and store callback
00213    PyROOT::Utility::InstallMethod( &gcl, pyclass, clName, 0, "ellipsis", (void*)PyCtorCallback );
00214 
00215 // loop over and add member functions
00216    for ( int i = 0; i < PyList_GET_SIZE( attrs ); ++i ) {
00217       PyObject* label = PyList_GET_ITEM( attrs, i );
00218       Py_INCREF( label );
00219       PyObject* attr = PyObject_GetAttr( pyclass, label );
00220 
00221    // collect only member functions (i.e. callable elements in __dict__)
00222       if ( PyCallable_Check( attr ) ) {
00223          std::string mtName = PyROOT_PyUnicode_AsString( label );
00224 
00225       // add method and store callback
00226          if ( mtName != "__init__" ) {
00227             PyROOT::Utility::InstallMethod(
00228                &gcl, attr, mtName, "TPyReturn", "ellipsis", (void*)PyMemFuncCallback );
00229          }
00230       }
00231 
00232       Py_DECREF( attr );
00233       Py_DECREF( label );
00234    }
00235 
00236    G__tag_memfunc_reset();
00237 
00238 // done, let ROOT manage the new class
00239    Py_DECREF( pyclass );
00240 
00241    TClass* klass = new TClass( clName.c_str(), silent );
00242    TClass::AddClass( klass );
00243 
00244    return klass;
00245 }
00246 
00247 //____________________________________________________________________________
00248 TClass* TPyClassGenerator::GetClass( const type_info& typeinfo, Bool_t load, Bool_t silent )
00249 {
00250    return GetClass( typeinfo.name(), load, silent );
00251 }
00252 //____________________________________________________________________________
00253 TClass* TPyClassGenerator::GetClass( const type_info& typeinfo, Bool_t load )
00254 {
00255 // just forward, based on name only
00256    return GetClass( typeinfo.name(), load );
00257 }

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