58 typedef std::map< Cppyy::TCppScope_t, PyObject* > PyClassMap_t;
59 PyClassMap_t gPyClasses;
62 PyObject* CreateNewROOTPythonClass(
const std::string& name,
PyObject* pybases )
65 Py_XINCREF( pybases );
67 pybases = PyTuple_New( 1 );
72 PyObject* pymetabases = PyTuple_New( PyTuple_GET_SIZE( pybases ) );
73 for (
int i = 0; i < PyTuple_GET_SIZE( pybases ); ++i ) {
76 PyTuple_SET_ITEM( pymetabases, i, btype );
79 PyObject* args = Py_BuildValue( (
char*)
"sO{}", (name+
"_meta").c_str(), pymetabases );
80 Py_DECREF( pymetabases );
90 args = Py_BuildValue( (
char*)
"sO{}", name.c_str(), pybases );
91 PyObject* pyclass = ((PyTypeObject*)pymeta)->tp_new( (PyTypeObject*)pymeta, args,
NULL );
100 inline void AddPropertyToClass1(
104 PyObject_SetAttrString( pyclass,
105 const_cast< char* >( property->
GetName().c_str() ), (
PyObject*)property );
110 const_cast< char* >( property->
GetName().c_str() ), (
PyObject*)property );
114 void AddPropertyToClass(
PyObject* pyclass,
119 Py_DECREF( property );
122 void AddPropertyToClass(
PyObject* pyclass,
127 AddPropertyToClass1( pyclass, property,
kTRUE );
128 Py_DECREF( property );
140 inline void AddToGlobalScope(
145 PyModule_AddObject(
gRootModule, const_cast< char* >( label ),
149 std::set< std::string > gSTLTypes, gSTLExceptions;
150 struct InitSTLTypes_t {
154 const std::string nss =
"std::";
156 const char* stlTypes[] = {
"complex",
"exception",
157 "deque",
"list",
"queue",
"stack",
"vector",
158 "map",
"multimap",
"set",
"multiset" };
159 for (
int i = 0; i < int(
sizeof(stlTypes)/
sizeof(stlTypes[0])); ++i ) {
160 gSTLTypes.insert( stlTypes[ i ] );
161 gSTLTypes.insert( nss + stlTypes[ i ] );
164 const char* stlExceptions[] = {
"logic_error",
"domain_error",
165 "invalid_argument",
"length_error",
"out_of_range",
"runtime_error",
166 "range_error",
"overflow_error",
"underflow_error" };
167 for (
int i = 0; i < int(
sizeof(stlExceptions)/
sizeof(stlExceptions[0])); ++i ) {
168 gSTLExceptions.insert( stlExceptions[ i ] );
169 gSTLExceptions.insert( nss + stlExceptions[ i ] );
174 Bool_t LoadDictionaryForSTLType(
const std::string& tname,
void* )
178 std::string sub = tname.substr( 0, tname.find(
"<" ) );
179 if ( gSTLTypes.find( sub ) != gSTLTypes.end() ) {
182 if ( sub.substr( 0, 5 ) ==
"std::" )
183 sub = sub.substr( 5, std::string::npos );
186 gROOT->ProcessLine( (std::string(
"#include <" ) + sub +
">").c_str() );
189 gSTLTypes.erase( gSTLTypes.find( sub ) );
190 gSTLTypes.erase( gSTLTypes.find(
"std::" + sub ) );
194 }
else if ( gSTLExceptions.find( sub ) != gSTLExceptions.end() ) {
200 gROOT->ProcessLine(
"#include <stdexcept>" );
201 gSTLExceptions.clear();
204 std::set< std::string >::iterator excpos = gSTLTypes.find(
"exception" );
205 if ( excpos != gSTLTypes.end() ) {
206 gSTLTypes.erase( excpos );
207 gSTLTypes.erase( gSTLTypes.find(
"std::exception" ) );
225 PyEval_InitThreads();
229 gROOT->GetListOfCleanups()->Add( &m );
247 typedef std::vector< PyCallable* > Callables_t;
248 typedef std::map< std::string, Callables_t > CallableCache_t;
249 CallableCache_t cache;
252 getattrofunc oldgetattro =
Py_TYPE(pyclass)->tp_getattro;
253 Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
274 if ( mtName[0] ==
'~' )
281 if ( mtName ==
"__call__" || mtName ==
"__getitem__" ) {
283 if ( qual_return.find(
"const", 0, 5 ) == std::string::npos ) {
285 if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] ==
'&' ) {
286 setupSetItem =
kTRUE;
295 std::string tmplName =
"";
296 if ( ! (isNamespace || isStatic || isConstructor) && mtName[mtName.size()-1] ==
'>' ) {
297 tmplName = mtName.substr( 0, mtName.find(
'<') );
300 PyObject*
attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
305 PyObject_SetAttrString(
306 pyclass, const_cast< char* >( tmplName.c_str() ), (
PyObject*)pytmpl );
323 mtName =
"_" + clName +
"__" + mtName;
331 else if ( isNamespace )
333 else if ( isConstructor ) {
336 hasConstructor =
kTRUE;
341 Callables_t& md = (*(cache.insert(
342 std::make_pair( mtName, Callables_t() ) ).first)).second;
343 md.push_back( pycall );
346 if ( setupSetItem ) {
347 Callables_t& setitem = (*(cache.insert(
348 std::make_pair( std::string(
"__setitem__" ), Callables_t() ) ).first)).second;
353 if ( ! tmplName.empty() ) {
354 PyObject*
attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
361 if ( ! isNamespace && ! hasConstructor )
365 for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
369 PyObject*
attr = PyObject_GetAttrString( pyclass, const_cast< char* >( imd->first.c_str() ) );
372 for ( Callables_t::iterator cit = imd->second.begin(); cit != imd->second.end(); ++cit )
375 if ( ! attr ) PyErr_Clear();
378 PyObject_SetAttrString(
379 pyclass, const_cast< char* >( method->
GetName().c_str() ), (
PyObject*)method );
389 TIter ienum( enums );
414 PyObject* eset = PyObject_GetAttrString( pyclass,
426 AddPropertyToClass( pyclass, scope, idata );
432 AddPropertyToClass( pyclass, scope, idata );
436 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
450 std::vector< std::string > uqb;
451 uqb.reserve( nbases );
453 for (
size_t ibase = 0; ibase < nbases; ++ibase ) {
455 if ( std::find( uqb.begin(), uqb.end(),
name ) == uqb.end() ) {
456 uqb.push_back( name );
463 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
472 for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
475 Py_DECREF( pybases );
479 PyTuple_SET_ITEM( pybases, ibase, pyclass );
485 PyObject* newpybases = PyTuple_New( nbases + 1 );
488 for (
int ibase = 0; ibase < (int)nbases; ++ibase ) {
489 PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
490 Py_INCREF( pyclass );
491 PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
493 Py_DECREF( pybases );
494 pybases = newpybases;
506 PyClassMap_t::iterator pci = gPyClasses.find( scope );
507 if ( pci != gPyClasses.end() ) {
508 PyObject* pyclass = PyWeakref_GetObject( pci->second );
510 Py_INCREF( pyclass );
536 if ( PyErr_Occurred() )
547 if ( scope_name.empty() || scope_name ==
"std" ) {
549 PyObject* mods = PyImport_GetModuleDict();
550 PyObject*
gbl = PyDict_GetItemString( mods,
"cppyy.gbl" );
552 if ( scope_name.empty() ) {
556 return PyObject_GetAttrString( gbl,
"std" );
558 PyErr_SetString( PyExc_SystemError,
"could not locate global namespace" );
563 Bool_t force = parent != 0;
566 std::string name = scope_name;
569 std::string scName =
"";
573 PyErr_Format( PyExc_SystemError,
"given scope has no name for %s", name.c_str() );
579 Py_DECREF( pyparent );
580 if ( PyErr_Occurred() )
588 const std::string&
lookup = parent ? (scName+
"::"+
name) : name;
594 if ( LoadDictionaryForSTLType( name, (
void*)klass ) ) {
603 PyObject* pytemplate = PyObject_CallFunction(
604 pytcl, const_cast< char* >(
"s" ), const_cast< char* >( lookup.c_str() ) );
608 PyObject_SetAttrString( parent ? parent :
gRootModule, (
char*)name.c_str(), pytemplate );
611 Py_XDECREF( parent );
616 if ( ! parent && scope_name.find(
"ROOT::" ) == std::string::npos ) {
627 PyErr_Format( PyExc_TypeError,
"requested class \'%s\' does not exist", lookup.c_str() );
628 Py_XDECREF( parent );
635 if ( parent ) PyObject_SetAttrString( parent, (
char*)scope_name.c_str(), pyscope );
640 std::string::size_type last = 0;
644 for ( std::string::size_type pos = 0; pos < name.size(); ++pos ) {
645 std::string::value_type
c = name[ pos ];
654 else if ( tpl_open == 0 &&\
655 c ==
':' && pos+1 < name.size() && name[ pos+1 ] ==
':' ) {
657 const std::string& part = name.substr( last, pos-last );
660 parent ? parent :
gRootModule, const_cast< char* >( part.c_str() ) );
666 Py_XDECREF( parent );
683 std::string unscoped = scope_name.substr( last, std::string::npos );
684 return PyObject_GetAttrString( parent, unscoped.c_str() );
699 PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
710 if ( pybases != 0 ) {
712 pyclass = CreateNewROOTPythonClass( actual, pybases );
713 Py_DECREF( pybases );
717 if ( pyclass != 0 ) {
720 Py_DECREF( pyclass );
723 PyObject_SetAttr( parent, pyactual, pyclass );
728 if ( pyclass && name != actual )
729 PyObject_SetAttrString( parent, const_cast< char* >( name.c_str() ), pyclass );
731 Py_DECREF( pyactual );
734 if ( pyclass && ! bClassFound ) {
736 gPyClasses[ klass ] = PyWeakref_NewRef( pyclass,
NULL );
742 if ( ! bClassFound ) {
744 Py_XDECREF( pyclass );
752 std::string pyfullname =
lookup;
753 std::string::size_type pos = pyfullname.find(
"::" );
754 while ( pos != std::string::npos ) {
755 pyfullname = pyfullname.replace( pos, 2,
"." );
756 pos = pyfullname.find(
"::", pos );
758 PyObject* modules = PySys_GetObject( const_cast<char*>(
"modules") );
759 if ( modules && PyDict_Check( modules) ) {
760 PyDict_SetItemString( modules,
761 const_cast<char*>((
"ROOT."+pyfullname).c_str()), pyclass );
776 if ( PyErr_Occurred() )
792 const std::vector< Cppyy::TCppMethod_t >& methods =
794 if ( ! methods.empty() ) {
795 std::vector< PyCallable* > overloads;
796 for (
auto method : methods )
809 PyErr_Format( PyExc_LookupError,
"no such global: %s", name.c_str() );
819 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
831 (
ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args,
NULL );
833 Py_DECREF( pyclass );
856 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
879 PyObject* oldPyObject = TMemoryRegulator::RetrieveObject(
object, clActual ? clActual : klass );
885 if ( clActual && klass != clActual ) {
887 clActual, klass, address, -1 ,
true );
888 if ( offset != -1 ) {
889 address = (
void*)((
Long_t)address + offset);
896 Bool_t ignore_pin = std::find(
899 if ( ! ignore_pin ) {
901 if ( klass == std::get<0>(*it) ||
Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
902 klass = std::get<1>(*it);
913 TMemoryRegulator::RegisterObject( pyobj,
object );
934 if ( ! gbl || strcmp(gbl->
GetName(),
"") == 0 ) {
935 Py_INCREF( Py_None );
946 PyErr_SetString( PyExc_NotImplementedError,
947 "larger than 1D arrays of objects not supported" );
962 (
unsigned long)gbl->
GetAddress() != (
unsigned long)-1 &&
964 return PyInt_FromLong( (
long)*((
int*)gbl->
GetAddress()) );
virtual const char * GetTypeName() const
Get type of global variable, e,g.
#define PyROOT_PyUnicode_FromString
The TEnum class implements the enum type.
std::string GetScopedFinalName(TCppType_t type)
R__EXTERN Int_t gErrorIgnoreLevel
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Bool_t IsNamespace(TCppScope_t scope)
virtual PyCallable * Clone()=0
All ROOT classes may have RTTI (run time type identification) support added.
TList * GetListOfEnums(Bool_t load=kTRUE)
Return list containing the TEnums of a class.
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Bool_t IsPublicMethod(TCppMethod_t method)
TCppIndex_t GetNumBases(TCppType_t type)
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
R__EXTERN PyObject * gTemplate
std::string GetFinalName(TCppType_t type)
Bool_t PyRootType_Check(T *object)
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
struct staticInitHelper gbl
TemplateProxy * TemplateProxy_New(const std::string &name, PyObject *pyclass)
Bool_t IsEnumData(TCppScope_t scope, TCppIndex_t idata)
std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
virtual Int_t GetArrayDim() const
Return number of array dimensions.
PyObject * BindCppObjectArray(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Int_t size)
TODO: this function exists for symmetry; need to figure out if it's useful.
std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
const TSeqCollection * GetConstants() const
Sequenceable collection abstract base class.
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
std::string ResolveName(const std::string &cppitem_name)
std::vector< Cppyy::TCppType_t > gIgnorePinnings
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
R__EXTERN PyObject * gRootModule
PyObject * GetCppGlobal(const std::string &name)
try named global variable/enum (first ROOT, then Cling: sync is too slow)
if(pyself &&pyself!=Py_None)
TCppIndex_t GetNumDatamembers(TCppScope_t scope)
#define PyROOT_PyUnicode_AsString
PropertyProxy * PropertyProxy_NewConstant(Cppyy::TCppScope_t scope, const std::string &name, void *address)
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
Bool_t IsConstructor(TCppMethod_t method)
TCppType_t GetActualClass(TCppType_t klass, TCppObject_t obj)
PyTypeObject PyRootType_Type
PyTypeObject ObjectProxy_Type
Bool_t IsPublicData(TCppScope_t scope, TCppIndex_t idata)
std::string GetMethodName(TCppMethod_t)
R__EXTERN PyObject * gROOTns
Long_t GetOffset() const
Get offset from "this".
R__EXTERN TSystem * gSystem
void * GetAddress() const override
Return address of global.
std::vector< std::pair< Cppyy::TCppType_t, Cppyy::TCppType_t > > gPinnedTypes
PyObject * BindCppGlobal(TGlobal *)
gbl == 0 means global does not exist (rather than gbl is NULL pointer)
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE, Bool_t isValue=kFALSE)
only known or knowable objects will be bound (null object is ok)
virtual const char * GetName() const
Returns name of object.
The TEnumConstant class implements the constants of the enum type.
TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
The ROOT global object gROOT contains a list of all defined classes.
static int BuildScopeProxyDict(Cppyy::TCppScope_t scope, PyObject *pyclass)
Collect methods and data for the given scope, and add them to the given python proxy object...
Global variables class (global variables are obtained from CINT).
PyObject * TTupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t nelems)
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
virtual Int_t GetSize() const
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
const RooCatType * lookup(Int_t idx) const
TCppScope_t GetScope(const std::string &scope_name)
std::string GetMethodResultType(TCppMethod_t)
R__EXTERN PyObject * gName
virtual void * GetAddress() const
Return address of global.
TCppIndex_t GetMethodNumArgs(TCppMethod_t)
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
virtual TObject * At(Int_t idx) const =0
Bool_t IsStaticMethod(TCppMethod_t method)
Mother of all ROOT objects.
std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
const std::string & GetName() const
Bool_t IsStaticData(TCppScope_t scope, TCppIndex_t idata)
TCppIndex_t GetNumMethods(TCppScope_t scope)
static PyObject * BuildCppClassBases(Cppyy::TCppType_t klass)
Build a tuple of python shadow classes of all the bases of the given 'klass'.
PropertyProxy * PropertyProxy_New(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
Retrieve scope proxy from the known ones.
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
Bool_t MethodProxy_Check(T *object)
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE)
if the object is a null pointer, return a typed one (as needed for overloading)
Template proxy object to return functions and methods.
void Set(void *address, EFlags flags=kNone)
Bool_t TemplateProxy_Check(T *object)
Bool_t Pythonize(PyObject *pyclass, const std::string &name)
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.