58 typedef std::map< Cppyy::TCppScope_t, PyObject* > PyClassMap_t;
59 PyClassMap_t gPyClasses;
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{}",
Cppyy::GetName(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 ] );
180 PyEval_InitThreads();
184 gROOT->GetListOfCleanups()->Add( &m );
202 typedef std::vector< PyCallable* > Callables_t;
203 typedef std::map< std::string, Callables_t > CallableCache_t;
204 CallableCache_t cache;
207 getattrofunc oldgetattro =
Py_TYPE(pyclass)->tp_getattro;
208 Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
229 if ( mtName[0] ==
'~' )
236 if ( mtName ==
"__call__" || mtName ==
"__getitem__" ) {
238 if ( qual_return.find(
"const", 0, 5 ) == std::string::npos ) {
240 if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] ==
'&' ) {
241 setupSetItem =
kTRUE;
250 std::string tmplName =
"";
251 if ( ! (isNamespace || isStatic || isConstructor) && mtName[mtName.size()-1] ==
'>' ) {
252 tmplName = mtName.substr( 0, mtName.find(
'<') );
255 PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
260 PyObject_SetAttrString(
261 pyclass, const_cast< char* >( tmplName.c_str() ), (
PyObject*)pytmpl );
278 mtName =
"_" + clName +
"__" + mtName;
286 else if ( isNamespace )
288 else if ( isConstructor ) {
291 hasConstructor =
kTRUE;
296 Callables_t& md = (*(cache.insert(
297 std::make_pair( mtName, Callables_t() ) ).first)).second;
298 md.push_back( pycall );
301 if ( setupSetItem ) {
302 Callables_t& setitem = (*(cache.insert(
303 std::make_pair( std::string(
"__setitem__" ), Callables_t() ) ).first)).second;
308 if ( ! tmplName.empty() ) {
309 PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( tmplName.c_str() ) );
316 if ( ! isNamespace && ! hasConstructor )
320 for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
324 PyObject* attr = PyObject_GetAttrString( pyclass, const_cast< char* >( imd->first.c_str() ) );
327 for ( Callables_t::iterator cit = imd->second.begin(); cit != imd->second.end(); ++cit )
330 if ( ! attr ) PyErr_Clear();
333 PyObject_SetAttrString(
334 pyclass, const_cast< char* >( method->
GetName().c_str() ), (
PyObject*)method );
344 TIter ienum( enums );
369 PyObject* eset = PyObject_GetAttrString( pyclass,
381 AddPropertyToClass( pyclass, scope, idata );
387 AddPropertyToClass( pyclass, scope, idata );
391 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
405 std::vector< std::string > uqb;
406 uqb.reserve( nbases );
408 for (
size_t ibase = 0; ibase < nbases; ++ibase ) {
410 if ( std::find( uqb.begin(), uqb.end(),
name ) == uqb.end() ) {
411 uqb.push_back( name );
418 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
425 PyTuple_SET_ITEM( pybases, 0, (
PyObject*)(
void*)&ObjectProxy_Type );
427 for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
430 Py_DECREF( pybases );
434 PyTuple_SET_ITEM( pybases, ibase, pyclass );
440 PyObject* newpybases = PyTuple_New( nbases + 1 );
441 Py_INCREF( (
PyObject*)(
void*)&ObjectProxy_Type );
442 PyTuple_SET_ITEM( newpybases, 0, (
PyObject*)(
void*)&ObjectProxy_Type );
443 for (
int ibase = 0; ibase < (int)nbases; ++ibase ) {
444 PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
445 Py_INCREF( pyclass );
446 PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
448 Py_DECREF( pybases );
449 pybases = newpybases;
461 PyClassMap_t::iterator pci = gPyClasses.find( scope );
462 if ( pci != gPyClasses.end() ) {
463 PyObject* pyclass = PyWeakref_GetObject( pci->second );
465 Py_INCREF( pyclass );
491 if ( PyErr_Occurred() )
502 if ( scope_name.empty() || scope_name ==
"std" ) {
504 PyObject* mods = PyImport_GetModuleDict();
505 PyObject* gbl = PyDict_GetItemString( mods,
"cppyy.gbl" );
507 if ( scope_name.empty() ) {
511 return PyObject_GetAttrString( gbl,
"std" );
513 PyErr_SetString( PyExc_SystemError,
"could not locate global namespace" );
518 Bool_t force = parent != 0;
521 std::string name = scope_name;
524 std::string scName =
"";
529 PyErr_Format( PyExc_SystemError,
"given scope has no name for %s", name.c_str() );
535 Py_DECREF( pyparent );
536 if ( PyErr_Occurred() )
544 const std::string& lookup = parent ? (scName+
"::"+
name) : name;
550 PyObject* pytemplate = PyObject_CallFunction(
551 pytcl, const_cast< char* >(
"s" ), const_cast< char* >( lookup.c_str() ) );
555 PyObject_SetAttrString( parent ? parent :
gRootModule, (
char*)name.c_str(), pytemplate );
558 Py_XDECREF( parent );
563 if ( ! parent && scope_name.find(
"ROOT::" ) == std::string::npos ) {
574 PyErr_Format( PyExc_TypeError,
"requested class \'%s\' does not exist", lookup.c_str() );
575 Py_XDECREF( parent );
582 if ( parent ) PyObject_SetAttrString( parent, (
char*)scope_name.c_str(), pyscope );
587 std::string::size_type last = 0;
591 for ( std::string::size_type pos = 0; pos < name.size(); ++pos ) {
592 std::string::value_type
c = name[ pos ];
601 else if ( tpl_open == 0 &&\
602 c ==
':' && pos+1 < name.size() && name[ pos+1 ] ==
':' ) {
604 const std::string& part = name.substr( last, pos-last );
606 PyObject* next = PyObject_GetAttrString(
607 parent ? parent :
gRootModule, const_cast< char* >( part.c_str() ) );
613 Py_XDECREF( parent );
630 std::string unscoped = scope_name.substr( last, std::string::npos );
631 return PyObject_GetAttrString( parent, unscoped.c_str() );
646 PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
657 if ( pybases != 0 ) {
659 pyclass = CreateNewROOTPythonClass( actual, pybases );
660 Py_DECREF( pybases );
664 if ( pyclass != 0 ) {
667 Py_DECREF( pyclass );
670 PyObject_SetAttr( parent, pyactual, pyclass );
676 if ( pyclass && name != actual )
677 PyObject_SetAttrString( parent, const_cast< char* >( name.c_str() ), pyclass );
679 if ( pyclass && ! bClassFound ) {
681 gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
709 Py_DECREF( pyactual );
713 if ( ! bClassFound ) {
715 Py_XDECREF( pyclass );
721 if ( pyclass && actual !=
"ROOT" ) {
723 std::string pyfullname = lookup;
724 std::string::size_type pos = pyfullname.find(
"::" );
725 while ( pos != std::string::npos ) {
726 pyfullname = pyfullname.replace( pos, 2,
"." );
727 pos = pyfullname.find(
"::", pos );
729 PyObject* modules = PySys_GetObject( const_cast<char*>(
"modules") );
730 if ( modules && PyDict_Check( modules) ) {
731 PyDict_SetItemString( modules,
732 const_cast<char*>((
"ROOT."+pyfullname).c_str()), pyclass );
747 if ( PyErr_Occurred() )
763 const std::vector< Cppyy::TCppMethod_t >& methods =
765 if ( ! methods.empty() ) {
766 std::vector< PyCallable* > overloads;
767 for (
auto method : methods )
780 PyErr_Format( PyExc_LookupError,
"no such global: %s", name.c_str() );
790 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
802 (
ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
804 Py_DECREF( pyclass );
827 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
856 if ( clActual && klass != clActual ) {
858 clActual, klass, address, -1 ,
true );
859 if ( offset != -1 ) {
860 address = (
void*)((
Long_t)address + offset);
867 Bool_t ignore_pin = std::find(
870 if ( ! ignore_pin ) {
872 if ( klass == std::get<0>(*it) ||
Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
873 klass = std::get<1>(*it);
905 if ( ! gbl || strcmp(gbl->
GetName(),
"") == 0 ) {
906 Py_INCREF( Py_None );
917 PyErr_SetString( PyExc_NotImplementedError,
918 "larger than 1D arrays of objects not supported" );
933 (
unsigned long)gbl->
GetAddress() != (
unsigned long)-1 &&
935 return PyInt_FromLong( (
long)*((
int*)gbl->
GetAddress()) );
virtual const char * GetName() const
Returns name of object.
std::string GetName(const std::string &scope_name)
#define PyROOT_PyUnicode_FromString
static PyObject * RetrieveObject(TObject *object, Cppyy::TCppType_t klass)
lookup <object>, return old proxy if tracked
The TEnum class implements the enum type.
std::string GetScopedFinalName(TCppType_t type)
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
R__EXTERN Int_t gErrorIgnoreLevel
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
Bool_t IsNamespace(TCppScope_t scope)
virtual PyCallable * Clone()=0
static Bool_t RegisterObject(ObjectProxy *pyobj, TObject *object)
start tracking <object> proxied by <pyobj>
All ROOT classes may have RTTI (run time type identification) support added.
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a 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)
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)
virtual void * GetAddress() const
Return address of global.
Bool_t PyRootType_Check(T *object)
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
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)
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.
const TSeqCollection * GetConstants() const
std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
Sequenceable collection abstract base class.
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)
R__EXTERN PyObject * gModule
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)
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
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)
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)
virtual Int_t GetArrayDim() const
Return number of array dimensions.
Long_t GetOffset() const
Get offset from "this".
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
virtual const char * GetTypeName() const
Get type of global variable, e,g.
TCppScope_t GetScope(const std::string &scope_name)
const std::string & GetName() const
std::string GetMethodResultType(TCppMethod_t)
R__EXTERN PyObject * gName
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
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.
R__EXTERN PyObject * gCppName
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)
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)
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
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.