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 ] );
182 PyEval_InitThreads();
186 gROOT->GetListOfCleanups()->Add( &
m );
204 typedef std::vector< PyCallable* > Callables_t;
205 typedef std::map< std::string, Callables_t > CallableCache_t;
206 CallableCache_t cache;
209 getattrofunc oldgetattro =
Py_TYPE(pyclass)->tp_getattro;
210 Py_TYPE(pyclass)->tp_getattro = PyType_Type.tp_getattro;
216 auto templName = templ->GetName();
217 auto attr = PyObject_GetAttrString(pyclass, templName);
220 PyObject_SetAttrString(pyclass, templName, (
PyObject*)templProxy);
221 Py_DECREF(templProxy);
246 if ( mtName[0] ==
'~' )
253 if ( mtName ==
"__call__" || mtName ==
"__getitem__" ) {
255 if ( qual_return.find(
"const", 0, 5 ) == std::string::npos ) {
257 if ( ! cpd.empty() && cpd[ cpd.size() - 1 ] ==
'&' ) {
258 setupSetItem =
kTRUE;
267 std::string tmplName =
"";
268 if ( ! (isNamespace || isStatic || isConstructor) && mtName[mtName.size()-1] ==
'>' ) {
269 tmplName = mtName.substr( 0, mtName.find(
'<') );
272 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( tmplName.c_str() ) );
277 PyObject_SetAttrString(
278 pyclass,
const_cast< char*
>( tmplName.c_str() ), (
PyObject*)pytmpl );
295 mtName =
"_" + clName +
"__" + mtName;
303 else if ( isNamespace )
305 else if ( isConstructor ) {
308 hasConstructor =
kTRUE;
313 Callables_t& md = (*(cache.insert(
314 std::make_pair( mtName, Callables_t() ) ).first)).second;
315 md.push_back( pycall );
318 if ( setupSetItem ) {
319 Callables_t& setitem = (*(cache.insert(
320 std::make_pair( std::string(
"__setitem__" ), Callables_t() ) ).first)).second;
325 if ( ! tmplName.empty() ) {
326 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( tmplName.c_str() ) );
333 if ( ! isNamespace && ! hasConstructor )
337 for ( CallableCache_t::iterator imd = cache.begin(); imd != cache.end(); ++imd ) {
341 PyObject* attr = PyObject_GetAttrString( pyclass,
const_cast< char*
>( imd->first.c_str() ) );
344 for ( Callables_t::iterator cit = imd->second.begin(); cit != imd->second.end(); ++cit )
347 if ( ! attr ) PyErr_Clear();
350 PyObject_SetAttrString(
351 pyclass,
const_cast< char*
>( method->
GetName().c_str() ), (
PyObject*)method );
361 TIter ienum( enums );
366 if (isScoped)
continue;
388 PyObject* eset = PyObject_GetAttrString( pyclass,
400 AddPropertyToClass( pyclass, scope, idata );
406 AddPropertyToClass( pyclass, scope, idata );
410 Py_TYPE(pyclass)->tp_getattro = oldgetattro;
424 std::vector< std::string > uqb;
425 uqb.reserve( nbases );
427 for (
size_t ibase = 0; ibase < nbases; ++ibase ) {
429 if ( std::find( uqb.begin(), uqb.end(),
name ) == uqb.end() ) {
430 uqb.push_back(
name );
437 PyObject* pybases = PyTuple_New( nbases ? nbases : 1 );
446 for ( std::vector< std::string >::size_type ibase = 0; ibase < nbases; ++ibase ) {
449 Py_DECREF( pybases );
453 PyTuple_SET_ITEM( pybases, ibase, pyclass );
459 PyObject* newpybases = PyTuple_New( nbases + 1 );
462 for (
int ibase = 0; ibase < (int)nbases; ++ibase ) {
463 PyObject* pyclass = PyTuple_GET_ITEM( pybases, ibase );
464 Py_INCREF( pyclass );
465 PyTuple_SET_ITEM( newpybases, ibase + 1, pyclass );
467 Py_DECREF( pybases );
468 pybases = newpybases;
480 PyClassMap_t::iterator pci = gPyClasses.find( scope );
481 if ( pci != gPyClasses.end() ) {
482 PyObject* pyclass = PyWeakref_GetObject( pci->second );
484 Py_INCREF( pyclass );
510 if ( PyErr_Occurred() )
521 if ( scope_name.empty() || scope_name ==
"std" ) {
523 PyObject* mods = PyImport_GetModuleDict();
524 PyObject* gbl = PyDict_GetItemString( mods,
"cppyy.gbl" );
526 if ( scope_name.empty() ) {
530 return PyObject_GetAttrString( gbl,
"std" );
532 PyErr_SetString( PyExc_SystemError,
"could not locate global namespace" );
537 Bool_t force = parent != 0;
540 std::string
name = scope_name;
543 std::string scName =
"";
551 PyErr_Format( PyExc_SystemError,
"given scope has no name for %s",
name.c_str() );
557 Py_DECREF( pyparent );
558 if ( PyErr_Occurred() )
566 const std::string& lookup = parent ? (scName+
"::"+
name) :
name;
572 PyObject* pytemplate = PyObject_CallFunction(
573 pytcl,
const_cast< char*
>(
"s" ),
const_cast< char*
>( lookup.c_str() ) );
577 PyObject_SetAttrString( parent ? parent :
gRootModule, (
char*)
name.c_str(), pytemplate );
580 Py_XDECREF( parent );
585 if ( ! parent && scope_name.find(
"ROOT::" ) == std::string::npos ) {
596 PyErr_Format( PyExc_TypeError,
"requested class \'%s\' does not exist", lookup.c_str() );
597 Py_XDECREF( parent );
604 if ( parent ) PyObject_SetAttrString( parent, (
char*)scope_name.c_str(), pyscope );
609 std::string::size_type last = 0;
613 for ( std::string::size_type pos = 0; pos <
name.size(); ++pos ) {
614 std::string::value_type
c =
name[ pos ];
623 else if ( tpl_open == 0 &&\
624 c ==
':' && pos+1 <
name.size() &&
name[ pos+1 ] ==
':' ) {
626 const std::string& part =
name.substr( last, pos-last );
628 PyObject* next = PyObject_GetAttrString(
629 parent ? parent :
gRootModule,
const_cast< char*
>( part.c_str() ) );
635 Py_XDECREF( parent );
652 std::string unscoped = scope_name.substr( last, std::string::npos );
653 return PyObject_GetAttrString( parent, unscoped.c_str() );
668 PyObject* pyclass = force ? 0 : PyObject_GetAttr( parent, pyactual );
679 if ( pybases != 0 ) {
681 pyclass = CreateNewROOTPythonClass( actual, pybases );
682 Py_DECREF( pybases );
686 if ( pyclass != 0 ) {
689 Py_DECREF( pyclass );
692 PyObject_SetAttr( parent, pyactual, pyclass );
698 if ( pyclass &&
name != actual )
699 PyObject_SetAttrString( parent,
const_cast< char*
>(
name.c_str() ), pyclass );
701 if ( pyclass && ! bClassFound ) {
703 gPyClasses[ klass ] = PyWeakref_NewRef( pyclass, NULL );
731 Py_DECREF( pyactual );
735 if ( ! bClassFound ) {
737 Py_XDECREF( pyclass );
743 if ( pyclass && actual !=
"ROOT" ) {
745 std::string pyfullname = lookup;
746 std::string::size_type pos = pyfullname.find(
"::" );
747 while ( pos != std::string::npos ) {
748 pyfullname = pyfullname.replace( pos, 2,
"." );
749 pos = pyfullname.find(
"::", pos );
751 PyObject* modules = PySys_GetObject(
const_cast<char*
>(
"modules") );
752 if ( modules && PyDict_Check( modules) ) {
753 PyDict_SetItemString( modules,
754 const_cast<char*
>((
"ROOT."+pyfullname).c_str()), pyclass );
769 if ( PyErr_Occurred() )
785 const std::vector< Cppyy::TCppMethod_t >& methods =
787 if ( ! methods.empty() ) {
788 std::vector< PyCallable* > overloads;
789 for (
auto method : methods )
807 PyErr_Format( PyExc_LookupError,
"no such global: %s",
name.c_str() );
817 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
829 (
ObjectProxy*)((PyTypeObject*)pyclass)->tp_new( (PyTypeObject*)pyclass, args, NULL );
831 Py_DECREF( pyclass );
854 PyErr_SetString( PyExc_TypeError,
"attempt to bind ROOT object w/o class" );
877 PyObject* oldPyObject = TMemoryRegulator::RetrieveObject(
object, clActual ? clActual : klass );
883 if ( clActual && klass != clActual ) {
885 clActual, klass, address, -1 ,
true );
886 if ( offset != -1 ) {
887 address = (
void*)((
Long_t)address + offset);
894 Bool_t ignore_pin = std::find(
897 if ( ! ignore_pin ) {
899 if ( klass == std::get<0>(*it) ||
Cppyy::IsSubtype( klass, std::get<0>(*it) ) )
900 klass = std::get<1>(*it);
911 TMemoryRegulator::RegisterObject( pyobj,
object );
932 if ( ! gbl || strcmp(gbl->
GetName(),
"") == 0 ) {
933 Py_INCREF( Py_None );
944 PyErr_SetString( PyExc_NotImplementedError,
945 "larger than 1D arrays of objects not supported" );
960 (
unsigned long)gbl->
GetAddress() != (
unsigned long)-1 &&
962 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.
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 * 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.