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 );
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 AddConstantPropertyToClass(
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 );
349 if (isScoped)
continue;
371 PyObject* eset = PyObject_GetAttrString( pyclass,
383 AddPropertyToClass( pyclass, scope, idata );
389 AddPropertyToClass( pyclass, scope, idata );
393 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
407 std::vector< std::string > uqb;
408 uqb.reserve( nbases );
410 for (
size_t ibase = 0; ibase < nbases; ++ibase ) {
412 if ( std::find( uqb.begin(), uqb.end(),
name ) == uqb.end() ) {
413 uqb.push_back(
name );
420 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
429 for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
432 Py_DECREF( pybases );
436 PyTuple_SET_ITEM( pybases, ibase, pyclass );
442 PyObject* newpybases = PyTuple_New( nbases + 1 );
445 for (
int ibase = 0; ibase < (int)nbases; ++ibase ) {
446 PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
447 Py_INCREF( pyclass );
448 PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
450 Py_DECREF( pybases );
451 pybases = newpybases;
463 PyClassMap_t::iterator pci = gPyClasses.find( scope );
464 if ( pci != gPyClasses.end() ) {
465 PyObject* pyclass = PyWeakref_GetObject( pci->second );
467 Py_INCREF( pyclass );
493 if ( PyErr_Occurred() )
504 if ( scope_name.empty() || scope_name ==
"std" ) {
506 PyObject* mods = PyImport_GetModuleDict();
507 PyObject* gbl = PyDict_GetItemString( mods,
"cppyy.gbl" );
509 if ( scope_name.empty() ) {
513 return PyObject_GetAttrString( gbl,
"std" );
515 PyErr_SetString( PyExc_SystemError,
"could not locate global namespace" );
520 Bool_t force = parent != 0;
523 std::string
name = scope_name;
526 std::string scName =
"";
534 PyErr_Format( PyExc_SystemError,
"given scope has no name for %s",
name.c_str() );
540 Py_DECREF( pyparent );
541 if ( PyErr_Occurred() )
549 const std::string& lookup = parent ? (scName+
"::"+
name) :
name;
555 PyObject* pytemplate = PyObject_CallFunction(
556 pytcl,
const_cast< char*
>(
"s" ),
const_cast< char*
>( lookup.c_str() ) );
560 PyObject_SetAttrString( parent ? parent :
gRootModule, (
char*)
name.c_str(), pytemplate );
563 Py_XDECREF( parent );
568 if ( ! parent && scope_name.find(
"ROOT::" ) == std::string::npos ) {
579 PyErr_Format( PyExc_TypeError,
"requested class \'%s\' does not exist", lookup.c_str() );
580 Py_XDECREF( parent );
587 if ( parent ) PyObject_SetAttrString( parent, (
char*)scope_name.c_str(), pyscope );
592 std::string::size_type last = 0;
596 for ( std::string::size_type pos = 0; pos <
name.size(); ++pos ) {
597 std::string::value_type
c =
name[ pos ];
606 else if ( tpl_open == 0 &&\
607 c ==
':' && pos+1 <
name.size() &&
name[ pos+1 ] ==
':' ) {
609 const std::string& part =
name.substr( last, pos-last );
611 PyObject* next = PyObject_GetAttrString(
612 parent ? parent :
gRootModule,
const_cast< char*
>( part.c_str() ) );
618 Py_XDECREF( parent );
635 std::string unscoped = scope_name.substr( last, std::string::npos );
636 return PyObject_GetAttrString( parent, unscoped.c_str() );
651 PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
662 if ( pybases != 0 ) {
664 pyclass = CreateNewROOTPythonClass( actual, pybases );
665 Py_DECREF( pybases );
669 if ( pyclass != 0 ) {
672 Py_DECREF( pyclass );
675 PyObject_SetAttr( parent, pyactual, pyclass );
681 if ( pyclass &&
name != actual )
682 PyObject_SetAttrString( parent,
const_cast< char*
>(
name.c_str() ), pyclass );
684 if ( pyclass && ! bClassFound ) {
686 gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
714 Py_DECREF( pyactual );
718 if ( ! bClassFound ) {
720 Py_XDECREF( pyclass );
726 if ( pyclass && actual !=
"ROOT" ) {
728 std::string pyfullname = lookup;
729 std::string::size_type pos = pyfullname.find(
"::" );
730 while ( pos != std::string::npos ) {
731 pyfullname = pyfullname.replace( pos, 2,
"." );
732 pos = pyfullname.find(
"::", pos );
734 PyObject* modules = PySys_GetObject(
const_cast<char*
>(
"modules") );
735 if ( modules && PyDict_Check( modules) ) {
736 PyDict_SetItemString( modules,
737 const_cast<char*
>((
"ROOT."+pyfullname).c_str()), pyclass );
752 if ( PyErr_Occurred() )
768 const std::vector< Cppyy::TCppMethod_t >& methods =
770 if ( ! methods.empty() ) {
771 std::vector< PyCallable* > overloads;
772 for (
auto method : methods )
785 PyErr_Format( PyExc_LookupError,
"no such global: %s",
name.c_str() );
795 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
807 (
ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
809 Py_DECREF( pyclass );
832 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
855 PyObject* oldPyObject = TMemoryRegulator::RetrieveObject(
object, clActual ? clActual : klass );
861 if ( clActual && klass != clActual ) {
863 clActual, klass, address, -1 ,
true );
864 if ( offset != -1 ) {
865 address = (
void*)((
Long_t)address + offset);
872 Bool_t ignore_pin = std::find(
875 if ( ! ignore_pin ) {
877 if ( klass == std::get<0>(*it) ||
Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
878 klass = std::get<1>(*it);
889 TMemoryRegulator::RegisterObject( pyobj,
object );
910 if ( ! gbl || strcmp(gbl->
GetName(),
"") == 0 ) {
911 Py_INCREF( Py_None );
922 PyErr_SetString( PyExc_NotImplementedError,
923 "larger than 1D arrays of objects not supported" );
938 (
unsigned long)gbl->
GetAddress() != (
unsigned long)-1 &&
940 return PyInt_FromLong( (
long)*((
int*)gbl->
GetAddress()) );
#define PyROOT_PyUnicode_AsString
#define PyROOT_PyUnicode_FromString
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.
static PyObject * BuildCppClassBases(Cppyy::TCppType_t klass)
Build a tuple of python shadow classes of all the bases of the given 'klass'.
R__EXTERN Int_t gErrorIgnoreLevel
R__EXTERN TSystem * gSystem
const std::string & GetName() const
void Set(void *address, EFlags flags=kNone)
virtual PyCallable * Clone()=0
Template proxy object to return functions and methods.
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
The ROOT global object gROOT contains a list of all defined classes.
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
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.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
All ROOT classes may have RTTI (run time type identification) support added.
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Long_t GetOffset() const
Get offset from "this".
The TEnumConstant class implements the constants of the enum type.
void * GetAddress() const override
Return address of global.
The TEnum class implements the enum type.
Global variables class (global variables are obtained from CINT).
virtual Int_t GetArrayDim() const
Return number of array dimensions.
virtual const char * GetTypeName() const
Get type of global variable, e,g.
virtual Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
virtual void * GetAddress() const
Return address of global.
virtual const char * GetFullTypeName() const
Get full type description of global variable, e,g.: "class TDirectory*".
virtual const char * GetName() const
Returns name of object.
Mother of all ROOT objects.
Sequenceable collection abstract base class.
virtual TObject * At(Int_t idx) const =0
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
Bool_t IsConstructor(TCppMethod_t method)
Bool_t IsPublicMethod(TCppMethod_t method)
Bool_t IsNamespace(TCppScope_t scope)
std::string GetMethodName(TCppMethod_t)
TCppIndex_t GetNumMethods(TCppScope_t scope)
TCppIndex_t GetNumDatamembers(TCppScope_t scope)
Bool_t IsPublicData(TCppScope_t scope, TCppIndex_t idata)
std::string GetName(const std::string &scope_name)
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name)
std::string ResolveName(const std::string &cppitem_name)
TCppType_t GetActualClass(TCppType_t klass, TCppObject_t obj)
std::string GetBaseName(TCppType_t type, TCppIndex_t ibase)
std::string GetScopedFinalName(TCppType_t type)
Bool_t IsEnumData(TCppScope_t scope, TCppIndex_t idata)
Bool_t IsStaticData(TCppScope_t scope, TCppIndex_t idata)
TCppIndex_t GetMethodNumArgs(TCppMethod_t)
TCppIndex_t GetDatamemberIndex(TCppScope_t scope, const std::string &name)
std::string GetDatamemberType(TCppScope_t scope, TCppIndex_t idata)
TCppScope_t GetScope(const std::string &scope_name)
Bool_t IsStaticMethod(TCppMethod_t method)
ptrdiff_t GetDatamemberOffset(TCppScope_t scope, TCppIndex_t idata)
std::string GetMethodResultType(TCppMethod_t)
std::string GetFinalName(TCppType_t type)
TCppIndex_t GetNumBases(TCppType_t type)
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
std::string GetDatamemberName(TCppScope_t scope, TCppIndex_t idata)
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
R__EXTERN PyObject * gName
R__EXTERN PyObject * gROOTns
R__EXTERN PyObject * gTemplate
R__EXTERN PyObject * gModule
R__EXTERN PyObject * gCppName
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.
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)
PyObject * GetScopeProxy(Cppyy::TCppScope_t)
Retrieve scope proxy from the known ones.
PyTypeObject PyRootType_Type
PropertyProxy * PropertyProxy_NewConstant(Cppyy::TCppScope_t scope, const std::string &name, void *address, TEnum *en)
PyObject * BindCppGlobal(TGlobal *)
gbl == 0 means global does not exist (rather than gbl is NULL pointer)
Bool_t PyRootType_Check(T *object)
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.
PyObject * TTupleOfInstances_New(Cppyy::TCppObject_t address, Cppyy::TCppType_t klass, Py_ssize_t nelems)
Bool_t TemplateProxy_Check(T *object)
PyTypeObject ObjectProxy_Type
TemplateProxy * TemplateProxy_New(const std::string &name, PyObject *pyclass)
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
Bool_t MethodProxy_Check(T *object)
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
PropertyProxy * PropertyProxy_New(Cppyy::TCppScope_t scope, Cppyy::TCppIndex_t idata)
std::vector< Cppyy::TCppType_t > gIgnorePinnings
std::vector< std::pair< Cppyy::TCppType_t, Cppyy::TCppType_t > > gPinnedTypes
R__EXTERN PyObject * gRootModule
PyObject * GetCppGlobal(const std::string &name)
try named global variable/enum (first ROOT, then Cling: sync is too slow)
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)
Bool_t Pythonize(PyObject *pyclass, const std::string &name)
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.