60 typedef std::map< Cppyy::TCppScope_t, PyObject* > PyClassMap_t;
61 PyClassMap_t gPyClasses;
67 Py_XINCREF( pybases );
69 pybases = PyTuple_New( 1 );
74 PyObject* pymetabases = PyTuple_New( PyTuple_GET_SIZE( pybases ) );
75 for (
int i = 0; i < PyTuple_GET_SIZE( pybases ); ++i ) {
78 PyTuple_SET_ITEM( pymetabases, i, btype );
81 PyObject* args = Py_BuildValue( (
char*)
"sO{}", (
name+
"_meta").c_str(), pymetabases );
82 Py_DECREF( pymetabases );
93 PyObject* pyclass = ((PyTypeObject*)pymeta)->tp_new( (PyTypeObject*)pymeta, args, NULL );
102 inline void AddPropertyToClass1(
106 PyObject_SetAttrString( pyclass,
107 const_cast< char*
>( property->
GetName().c_str() ), (
PyObject*)property );
112 const_cast< char*
>( property->
GetName().c_str() ), (
PyObject*)property );
116 void AddPropertyToClass(
PyObject* pyclass,
121 Py_DECREF( property );
124 void AddConstantPropertyToClass(
PyObject* pyclass,
129 AddPropertyToClass1( pyclass, property,
kTRUE );
130 Py_DECREF( property );
142 inline void AddToGlobalScope(
147 PyModule_AddObject(
gRootModule,
const_cast< char*
>( label ),
151 std::set< std::string > gSTLTypes, gSTLExceptions;
152 struct InitSTLTypes_t {
156 const std::string nss =
"std::";
158 const char* stlTypes[] = {
"complex",
"exception",
159 "deque",
"list",
"queue",
"stack",
"vector",
160 "map",
"multimap",
"set",
"multiset" };
161 for (
int i = 0; i < int(
sizeof(stlTypes)/
sizeof(stlTypes[0])); ++i ) {
162 gSTLTypes.insert( stlTypes[ i ] );
163 gSTLTypes.insert( nss + stlTypes[ i ] );
166 const char* stlExceptions[] = {
"logic_error",
"domain_error",
167 "invalid_argument",
"length_error",
"out_of_range",
"runtime_error",
168 "range_error",
"overflow_error",
"underflow_error" };
169 for (
int i = 0; i < int(
sizeof(stlExceptions)/
sizeof(stlExceptions[0])); ++i ) {
170 gSTLExceptions.insert( stlExceptions[ i ] );
171 gSTLExceptions.insert( nss + stlExceptions[ i ] );
187 PyEval_InitThreads();
208 typedef std::vector< PyCallable* > Callables_t;
209 typedef std::map< std::string, Callables_t > CallableCache_t;
210 CallableCache_t cache;
213 getattrofunc oldgetattro =
Py_TYPE(pyclass)->tp_getattro;
214 Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
220 auto templName = templ->GetName();
221 auto attr = PyObject_GetAttrString(pyclass, templName);
224 PyObject_SetAttrString(pyclass, templName, (
PyObject*)templProxy);
225 Py_DECREF(templProxy);
250 if ( mtName[0] ==
'~' )
257 if ( mtName ==
"__call__" || mtName ==
"__getitem__" ) {
259 if ( qual_return.find(
"const", 0, 5 ) == std::string::npos ) {
261 if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] ==
'&' ) {
262 setupSetItem =
kTRUE;
271 std::string tmplName =
"";
272 if ( ! (isNamespace || isStatic || isConstructor) && mtName[mtName.size()-1] ==
'>' ) {
273 tmplName = mtName.substr( 0, mtName.find(
'<') );
276 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( tmplName.c_str() ) );
281 PyObject_SetAttrString(
282 pyclass,
const_cast< char*
>( tmplName.c_str() ), (
PyObject*)pytmpl );
299 mtName =
"_" + clName +
"__" + mtName;
307 else if ( isNamespace )
309 else if ( isConstructor ) {
312 hasConstructor =
kTRUE;
317 Callables_t& md = (*(cache.insert(
318 std::make_pair( mtName, Callables_t() ) ).first)).second;
319 md.push_back( pycall );
322 if ( setupSetItem ) {
323 Callables_t& setitem = (*(cache.insert(
324 std::make_pair( std::string(
"__setitem__" ), Callables_t() ) ).first)).second;
329 if ( ! tmplName.empty() ) {
330 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( tmplName.c_str() ) );
337 if ( ! isNamespace && ! hasConstructor )
341 for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
345 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( imd->first.c_str() ) );
348 for ( Callables_t::iterator cit = imd->second.begin(); cit != imd->second.end(); ++cit )
351 if ( ! attr ) PyErr_Clear();
354 PyObject_SetAttrString(
355 pyclass,
const_cast< char*
>( method->
GetName().c_str() ), (
PyObject*)method );
365 TIter ienum( enums );
370 if (isScoped)
continue;
392 PyObject* eset = PyObject_GetAttrString( pyclass,
404 AddPropertyToClass( pyclass, scope, idata );
410 AddPropertyToClass( pyclass, scope, idata );
414 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
428 std::vector< std::string > uqb;
429 uqb.reserve( nbases );
431 for (
size_t ibase = 0; ibase < nbases; ++ibase ) {
433 if ( std::find( uqb.begin(), uqb.end(),
name ) == uqb.end() ) {
434 uqb.push_back(
name );
441 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
450 for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
453 Py_DECREF( pybases );
457 PyTuple_SET_ITEM( pybases, ibase, pyclass );
463 PyObject* newpybases = PyTuple_New( nbases + 1 );
466 for (
int ibase = 0; ibase < (int)nbases; ++ibase ) {
467 PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
468 Py_INCREF( pyclass );
469 PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
471 Py_DECREF( pybases );
472 pybases = newpybases;
484 PyClassMap_t::iterator pci = gPyClasses.find( scope );
485 if ( pci != gPyClasses.end() ) {
486 PyObject* pyclass = PyWeakref_GetObject( pci->second );
488 Py_INCREF( pyclass );
514 if ( PyErr_Occurred() )
525 if ( scope_name.empty() || scope_name ==
"std" ) {
527 PyObject* mods = PyImport_GetModuleDict();
528 PyObject* gbl = PyDict_GetItemString( mods,
"cppyy.gbl" );
530 if ( scope_name.empty() ) {
534 return PyObject_GetAttrString( gbl,
"std" );
536 PyErr_SetString( PyExc_SystemError,
"could not locate global namespace" );
541 Bool_t force = parent != 0;
544 std::string
name = scope_name;
547 std::string scName =
"";
555 PyErr_Format( PyExc_SystemError,
"given scope has no name for %s",
name.c_str() );
561 Py_DECREF( pyparent );
562 if ( PyErr_Occurred() )
570 const std::string& lookup = parent ? (scName+
"::"+
name) :
name;
576 PyObject* pytemplate = PyObject_CallFunction(
577 pytcl,
const_cast< char*
>(
"s" ),
const_cast< char*
>( lookup.c_str() ) );
581 PyObject_SetAttrString( parent ? parent :
gRootModule, (
char*)
name.c_str(), pytemplate );
584 Py_XDECREF( parent );
589 if ( ! parent && scope_name.find(
"ROOT::" ) == std::string::npos ) {
600 PyErr_Format( PyExc_TypeError,
"requested class \'%s\' does not exist", lookup.c_str() );
601 Py_XDECREF( parent );
608 if ( parent ) PyObject_SetAttrString( parent, (
char*)scope_name.c_str(), pyscope );
613 std::string::size_type last = 0;
617 for ( std::string::size_type pos = 0; pos <
name.size(); ++pos ) {
618 std::string::value_type
c =
name[ pos ];
627 else if ( tpl_open == 0 &&\
628 c ==
':' && pos+1 <
name.size() &&
name[ pos+1 ] ==
':' ) {
630 const std::string& part =
name.substr( last, pos-last );
632 PyObject* next = PyObject_GetAttrString(
633 parent ? parent :
gRootModule,
const_cast< char*
>( part.c_str() ) );
639 Py_XDECREF( parent );
656 std::string unscoped = scope_name.substr( last, std::string::npos );
657 return PyObject_GetAttrString( parent, unscoped.c_str() );
672 PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
683 if ( pybases != 0 ) {
685 pyclass = CreateNewROOTPythonClass( actual, pybases );
686 Py_DECREF( pybases );
690 if ( pyclass != 0 ) {
693 Py_DECREF( pyclass );
696 PyObject_SetAttr( parent, pyactual, pyclass );
702 if ( pyclass &&
name != actual )
703 PyObject_SetAttrString( parent,
const_cast< char*
>(
name.c_str() ), pyclass );
705 if ( pyclass && ! bClassFound ) {
707 gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
737 Py_DECREF( pyactual );
741 if ( ! bClassFound ) {
743 Py_XDECREF( pyclass );
749 if ( pyclass && actual !=
"ROOT" ) {
751 std::string pyfullname = lookup;
752 std::string::size_type pos = pyfullname.find(
"::" );
753 while ( pos != std::string::npos ) {
754 pyfullname = pyfullname.replace( pos, 2,
"." );
755 pos = pyfullname.find(
"::", pos );
757 PyObject* modules = PySys_GetObject(
const_cast<char*
>(
"modules") );
758 if ( modules && PyDict_Check( modules) ) {
759 PyDict_SetItemString( modules,
760 const_cast<char*
>((
"ROOT."+pyfullname).c_str()), pyclass );
775 if ( PyErr_Occurred() )
791 const std::vector< Cppyy::TCppMethod_t >& methods =
793 if ( ! methods.empty() ) {
794 std::vector< PyCallable* > overloads;
795 for (
auto method : methods )
813 PyErr_Format( PyExc_LookupError,
"no such global: %s",
name.c_str() );
832 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
844 (
ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
846 Py_DECREF( pyclass );
869 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
892 PyObject* oldPyObject = TMemoryRegulator::RetrieveObject(
object, clActual ? clActual : klass );
898 if ( clActual && klass != clActual ) {
900 clActual, klass, address, -1 ,
true );
901 if ( offset != -1 ) {
902 address = (
void*)((
Long_t)address + offset);
909 Bool_t ignore_pin = std::find(
912 if ( ! ignore_pin ) {
914 if ( klass == std::get<0>(*it) ||
Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
915 klass = std::get<1>(*it);
926 TMemoryRegulator::RegisterObject( pyobj,
object );
947 if ( ! gbl || strcmp(gbl->
GetName(),
"") == 0 ) {
948 Py_INCREF( Py_None );
959 PyErr_SetString( PyExc_NotImplementedError,
960 "larger than 1D arrays of objects not supported" );
975 (
unsigned long)gbl->
GetAddress() != (
unsigned long)-1 &&
977 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'.
static TMemoryRegulator & GetMemoryRegulator()
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
void ClearProxiedObjects()
clean up all tracked objects
Template proxy object to return functions and methods.
void AddOverload(MethodProxy *mp)
Store overloads of this templated method.
TRangeStaticCast is an adaptater class that allows the typed iteration through a TCollection.
TClass instances represent classes, structs and namespaces in the ROOT type system.
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)
bool ExistsMethodTemplate(TCppScope_t scope, const std::string &name)
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::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)
std::vector< TCppMethod_t > GetMethodsFromName(TCppScope_t scope, const std::string &name, bool alsoInBases=false)
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 * gCppNameNew
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)
PyObject * ClearProxiedObjects()
Delete all memory-regulated objects.
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.