52 using namespace PyROOT::Utility;
54 struct InitOperatorMapping_t {
56 InitOperatorMapping_t() {
64 gC2POperatorMapping[
"[]" ] =
"__getitem__";
65 gC2POperatorMapping[
"()" ] =
"__call__";
67 gC2POperatorMapping[
"%" ] =
"__mod__";
68 gC2POperatorMapping[
"**" ] =
"__pow__";
69 gC2POperatorMapping[
"<<" ] =
"__lshift__";
70 gC2POperatorMapping[
">>" ] =
"__rshift__";
71 gC2POperatorMapping[
"&" ] =
"__and__";
72 gC2POperatorMapping[
"|" ] =
"__or__";
73 gC2POperatorMapping[
"^" ] =
"__xor__";
74 gC2POperatorMapping[
"~" ] =
"__inv__";
75 gC2POperatorMapping[
"+=" ] =
"__iadd__";
76 gC2POperatorMapping[
"-=" ] =
"__isub__";
77 gC2POperatorMapping[
"*=" ] =
"__imul__";
79 gC2POperatorMapping[
"%=" ] =
"__imod__";
80 gC2POperatorMapping[
"**=" ] =
"__ipow__";
81 gC2POperatorMapping[
"<<=" ] =
"__ilshift__";
82 gC2POperatorMapping[
">>=" ] =
"__irshift__";
83 gC2POperatorMapping[
"&=" ] =
"__iand__";
84 gC2POperatorMapping[
"|=" ] =
"__ior__";
85 gC2POperatorMapping[
"^=" ] =
"__ixor__";
86 gC2POperatorMapping[
"==" ] =
"__eq__";
87 gC2POperatorMapping[
"!=" ] =
"__ne__";
88 gC2POperatorMapping[
">" ] =
"__gt__";
89 gC2POperatorMapping[
"<" ] =
"__lt__";
90 gC2POperatorMapping[
">=" ] =
"__ge__";
91 gC2POperatorMapping[
"<=" ] =
"__le__";
94 gC2POperatorMapping[
"const char*" ] =
"__str__";
95 gC2POperatorMapping[
"char*" ] =
"__str__";
96 gC2POperatorMapping[
"const char *" ] = gC2POperatorMapping[
"const char*" ];
97 gC2POperatorMapping[
"char *" ] = gC2POperatorMapping[
"char*" ];
98 gC2POperatorMapping[
"int" ] =
"__int__";
100 gC2POperatorMapping[
"double" ] =
"__float__";
105 gC2POperatorMapping[
"short" ] =
"__int__";
106 gC2POperatorMapping[
"unsigned short" ] =
"__int__";
111 gC2POperatorMapping[
"float" ] =
"__float__";
113 gC2POperatorMapping[
"->" ] =
"__follow__";
114 gC2POperatorMapping[
"=" ] =
"__assign__";
116 #if PY_VERSION_HEX < 0x03000000
117 gC2POperatorMapping[
"bool" ] =
"__nonzero__";
119 gC2POperatorMapping[
"bool" ] =
"__bool__";
122 } initOperatorMapping_;
124 std::once_flag sOperatorTemplateFlag;
125 void InitOperatorTemplate() {
127 "namespace _pyroot_internal { template<class C1, class C2>"
128 " bool is_equal(const C1& c1, const C2& c2){ return (bool)(c1 == c2); } }" );
130 "namespace _pyroot_internal { template<class C1, class C2>"
131 " bool is_not_equal(const C1& c1, const C2& c2){ return (bool)(c1 != c2); } }" );
134 inline void RemoveConst( std::string& cleanName ) {
135 std::string::size_type spos = std::string::npos;
136 while ( ( spos = cleanName.find(
"const" ) ) != std::string::npos ) {
137 cleanName.swap( cleanName.erase( spos, 5 ) );
148 ULong_t ul = PyLong_AsUnsignedLong( pyobject );
149 if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
151 Long_t i = PyInt_AS_LONG( pyobject );
155 PyErr_SetString( PyExc_ValueError,
156 "can\'t convert negative value to unsigned long" );
168 ULong64_t ull = PyLong_AsUnsignedLongLong( pyobject );
169 if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) {
171 Long_t i = PyInt_AS_LONG( pyobject );
175 PyErr_SetString( PyExc_ValueError,
176 "can\'t convert negative value to unsigned long long" );
187 PyObject* pyclass,
const char* label, PyCFunction cfunc,
int flags )
190 static std::list< PyMethodDef > s_pymeths;
192 s_pymeths.push_back( PyMethodDef() );
193 PyMethodDef* pdef = &s_pymeths.back();
194 pdef->ml_name =
const_cast< char*
>( label );
195 pdef->ml_meth = cfunc;
196 pdef->ml_flags = flags;
201 Bool_t isOk = PyObject_SetAttrString( pyclass, pdef->ml_name, method ) == 0;
205 if ( PyErr_Occurred() )
209 PyErr_Format( PyExc_TypeError,
"could not add method %s", label );
221 PyObject* pyfunc = PyObject_GetAttrString( pyclass, const_cast< char* >( func ) );
225 Bool_t isOk = PyObject_SetAttrString( pyclass, const_cast< char* >( label ), pyfunc ) == 0;
237 (
MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( label ) );
241 if ( PyErr_Occurred() )
245 Bool_t isOk = PyObject_SetAttrString(
246 pyclass, const_cast< char* >( label ), (
PyObject*)method ) == 0;
264 (
MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( method ) );
266 Py_XDECREF( derivedMethod );
271 if ( ! mro || ! PyTuple_Check( mro ) ) {
273 Py_DECREF( derivedMethod );
278 for (
int i = 1; i < PyTuple_GET_SIZE( mro ); ++i ) {
280 PyTuple_GET_ITEM( mro, i ),
const_cast< char*
>( method ) );
282 if ( ! baseMethod ) {
290 Py_DECREF( baseMethod );
297 Py_XDECREF( baseMethod );
298 Py_DECREF( derivedMethod );
304 Py_DECREF( baseMethod );
305 Py_DECREF( derivedMethod );
316 PyObject* left,
PyObject* right,
const char* op,
const char* label,
const char* alt )
329 Py_DECREF( pyclass );
337 PyObject* pyclass,
const char* op,
const char* label,
const char* alt )
341 Py_DECREF( pyname ); pyname = 0;
350 const char* op,
TClass* klass = 0 ) {
351 std::string opname =
"operator";
353 std::string proto = lcname +
", " + rcname;
360 return (
Cppyy::TCppMethod_t)klass->GetMethodWithPrototype( opname.c_str(), proto.c_str() );
364 const std::string& rcname,
const char* op,
const char* label,
const char* alt )
374 if ( !
gApplication && (strcmp( op,
"==" ) == 0 || strcmp( op,
"!=" ) == 0) )
388 std::call_once( sOperatorTemplateFlag, InitOperatorTemplate );
389 static TClassRef _pr_int(
"_pyroot_internal" );
397 if ( ! pyfunc && std__1.
GetClass() ) {
403 std::string::size_type pos = lcname.substr(0, lcname.find(
'<')).rfind(
"::" );
404 if ( pos != std::string::npos ) {
418 if ( ! pyfunc && _pr_int.
GetClass() &&
419 lcname.find(
"iterator" ) != std::string::npos &&
420 rcname.find(
"iterator" ) != std::string::npos ) {
424 std::stringstream fname;
425 if ( strncmp( op,
"==", 2 ) == 0 ) { fname <<
"is_equal<"; }
426 else if ( strncmp( op,
"!=", 2 ) == 0 ) { fname <<
"is_not_equal<"; }
427 else { fname <<
"not_implemented<"; }
428 fname << lcname <<
", " << rcname <<
">";
435 if ( lc && strcmp(op,
"==") != 0 && strcmp(op,
"!=") != 0 ) {
436 std::string opname =
"operator"; opname += op;
468 for (
int i = argoff; i < nArgs; ++i ) {
470 PyObject* tn = PyTuple_GET_ITEM( args, i );
489 if ( PyInt_Check( tn ) || PyLong_Check( tn ) || PyFloat_Check( tn ) )
490 pystr = PyObject_Str( tn );
500 if ( i != nArgs - 1 )
519 if ( PyType_Ready( pytype ) < 0 )
524 if ( PyModule_AddObject( module, (
char*)name, (
PyObject*)pytype ) < 0 ) {
543 PyBufferProcs* bufprocs =
Py_TYPE(pyobject)->tp_as_buffer;
545 PySequenceMethods* seqmeths =
Py_TYPE(pyobject)->tp_as_sequence;
546 if ( seqmeths != 0 && bufprocs != 0
547 #
if PY_VERSION_HEX < 0x03000000
548 && bufprocs->bf_getwritebuffer != 0
549 && (*(bufprocs->bf_getsegcount))( pyobject, 0 ) == 1
551 && bufprocs->bf_getbuffer != 0
556 #if PY_VERSION_HEX < 0x03000000
557 Py_ssize_t buflen = (*(bufprocs->bf_getwritebuffer))( pyobject, 0, &buf );
560 (*(bufprocs->bf_getbuffer))( pyobject, &bufinfo, PyBUF_WRITABLE );
561 buf = (
char*)bufinfo.buf;
572 }
else if ( seqmeths->sq_length &&
573 (
int)(buflen / (*(seqmeths->sq_length))( pyobject )) == size ) {
576 }
else if ( buflen == size ) {
583 PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
584 PyErr_Fetch( &pytype, &pyvalue, &pytrace );
586 (
char*)
"%s and given element size (%ld) do not match needed (%d)",
588 seqmeths->sq_length ? (
Long_t)(buflen / (*(seqmeths->sq_length))( pyobject )) : (
Long_t)buflen,
590 Py_DECREF( pyvalue );
591 PyErr_Restore( pytype, pyvalue2, pytrace );
606 if ( 8 < name.size() && name.substr( 0, 8 ) ==
"operator" ) {
607 std::string op = name.substr( 8, std::string::npos );
610 std::string::size_type
start = 0, end = op.size();
611 while ( start < end && isspace( op[ start ] ) ) ++
start;
612 while ( start < end && isspace( op[ end-1 ] ) ) --end;
616 TC2POperatorMapping_t::iterator pop = gC2POperatorMapping.find( op );
617 if ( pop != gC2POperatorMapping.end() ) {
620 }
else if ( op ==
"*" ) {
622 return bTakesParams ?
"__mul__" :
"__deref__";
624 }
else if ( op ==
"+" ) {
626 return bTakesParams ?
"__add__" :
"__pos__";
628 }
else if ( op ==
"-" ) {
630 return bTakesParams ?
"__sub__" :
"__neg__";
632 }
else if ( op ==
"++" ) {
634 return bTakesParams ?
"__postinc__" :
"__preinc__";
636 }
else if ( op ==
"--" ) {
638 return bTakesParams ?
"__postdec__" :
"__predec__";
652 std::string cleanName =
name;
653 RemoveConst( cleanName );
655 std::string compound =
"";
656 for (
int ipos = (
int)cleanName.size()-1; 0 <= ipos; --ipos ) {
657 char c = cleanName[ipos];
658 if ( isspace( c ) )
continue;
659 if ( isalnum( c ) || c ==
'_' || c ==
'>' )
break;
661 compound = c + compound;
665 if ( compound ==
"]" )
676 std::string cleanName =
name;
677 RemoveConst( cleanName );
679 if ( cleanName[cleanName.size()-1] ==
']' ) {
680 std::string::size_type idx = cleanName.rfind(
'[' );
681 if ( idx != std::string::npos ) {
682 const std::string asize = cleanName.substr( idx+1, cleanName.size()-2 );
683 return strtoul( asize.c_str(),
NULL, 0 );
696 std::string clname =
"<unknown>";
698 if ( pyclass != 0 ) {
707 Py_DECREF( pyclass );
808 PyErr_WarnExplicit(
NULL, (
char*)msg, (
char*)location, 0, (
char*)
"ROOT",
NULL );
821 const char* retType,
const std::vector<std::string>& signature,
const char* callback )
825 if ( ! PyCallable_Check( pyfunc ) )
834 std::ostringstream funcName;
835 funcName <<
"pyrootGenFun" << fid;
838 std::ostringstream sigDecl, argsig;
839 std::vector<std::string>::size_type nargs = signature.size();
840 for ( std::vector<std::string>::size_type i = 0; i < nargs; ++i ) {
841 sigDecl << signature[i] <<
" a" << i;
842 argsig <<
", a" << i;
843 if ( i != nargs-1 ) sigDecl <<
", ";
847 std::ostringstream declCode;
848 declCode <<
"namespace PyROOT { "
849 << retType <<
" " << callback <<
"(void*, Long_t, " << sigDecl.str() <<
"); }\n"
850 << retType <<
" " << funcName.str() <<
"(" << sigDecl.str()
851 <<
") { void* v0 = (void*)" << (
void*)pyfunc <<
"; "
852 <<
"return PyROOT::" << callback <<
"(v0, " << user << argsig.str() <<
"); }";
858 std::ostringstream fptrCode;
859 fptrCode <<
"void* pyrootPtrVar" << fid <<
" = (void*)" << funcName.str()
860 <<
"; pyrootPtrVar" << fid <<
";";
863 void* fptr = (
void*)
gInterpreter->ProcessLineSynch( fptrCode.str().c_str() );
865 PyErr_SetString( PyExc_SyntaxError,
"could not generate C++ callback wrapper" );
877 #if PY_VERSION_HEX >= 0x02030000
878 PyGILState_STATE gstate = PyGILState_Ensure();
880 PyGILState_Release( gstate );
882 if ( PyThreadState_GET() )
883 return PyErr_Occurred();
893 static int (*sOldInputHook)() =
NULL;
894 static PyThreadState* sInputHookEventThreadState =
NULL;
896 static int EventInputHook()
900 PyEval_RestoreThread( sInputHookEventThreadState );
904 if ( sOldInputHook )
return sOldInputHook();
913 if ( PyOS_InputHook && PyOS_InputHook != &EventInputHook )
914 sOldInputHook = PyOS_InputHook;
916 sInputHookEventThreadState = PyThreadState_Get();
918 PyOS_InputHook = (int (*)())&EventInputHook;
919 Py_INCREF( Py_None );
926 PyOS_InputHook = sOldInputHook;
927 sInputHookEventThreadState =
NULL;
929 Py_INCREF( Py_None );
Bool_t InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Initialize a proxy class for use by python, and add it to the ROOT module.
Bool_t AddBinaryOperator(PyObject *left, PyObject *right, const char *op, const char *label, const char *alt_label=NULL)
Install the named operator (op) into the left object's class if such a function exists as a global ov...
#define PyROOT_PyUnicode_FromString
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
R__EXTERN Int_t gErrorIgnoreLevel
PyObject * TCustomInstanceMethod_New(PyObject *func, PyObject *self, PyObject *pyclass)
Dictionary for function template This class describes one single function template.
void DefaultErrorHandler(int level, Bool_t abort, const char *location, const char *msg)
The default error handler function.
PyObject * RemoveGUIEventInputHook()
MethodProxy * MethodProxy_New(const std::string &name, std::vector< PyCallable * > &methods)
R__EXTERN dict_lookup_func gDictLookupOrg
PyObject * BuildTemplateName(PyObject *pyname, PyObject *args, int argoff)
Helper to construct the "< type, type, ... >" part of a templated name (either for a class as in Make...
R__EXTERN TApplication * gApplication
R__EXTERN Bool_t gDictLookupActive
#define PyROOT_PyUnicode_FromFormat
#define PyROOT_PyUnicode_Append
std::string ResolveName(const std::string &cppitem_name)
std::string MapOperatorName(const std::string &name, Bool_t bTakesParames)
Map the given C++ operator name on the python equivalent.
#define PyROOT_PyUnicode_GetSize
R__EXTERN PyObject * gMRO
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
if(pyself &&pyself!=Py_None)
const std::string ClassName(PyObject *pyobj)
Retrieve the class name from the given python object (which may be just an instance of the class)...
#define PyROOT_PyUnicode_AsString
PyObject * PyErr_Occurred_WithGIL()
Re-acquire the GIL before calling PyErr_Occurred() in case it has been released; note that the p2...
std::map< std::string, std::string > TC2POperatorMapping_t
static TC2POperatorMapping_t gC2POperatorMapping
ULong_t PyLongOrInt_AsULong(PyObject *pyobject)
void ErrMsgHandler(int level, Bool_t abort, const char *location, const char *msg)
Translate ROOT error/warning to python.
Bool_t ObjectProxy_Check(T *object)
R__EXTERN PyObject * gClass
R__EXTERN TSystem * gSystem
ClassInfo_t * GetClassInfo() const
ULong64_t PyLongOrInt_AsULong64(PyObject *pyobject)
Convert <pyobject> to C++ unsigned long long, with bounds checking.
The ROOT global object gROOT contains a list of all defined classes.
#define PyROOT_PyUnicode_AppendAndDel
PyObject * InstallGUIEventInputHook()
TCppScope_t GetScope(const std::string &scope_name)
R__EXTERN PyObject * gName
void AddMethod(PyCallable *pc)
Fill in the data of a freshly created method proxy.
R__EXTERN PyObject * gTypeCode
unsigned long long ULong64_t
double func(double *x, double *p)
Bool_t AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Add the given function to the class under name 'label'.
#define PyROOT_PyUnicode_Check
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.
Bool_t AddUsingToClass(PyObject *pyclass, const char *method)
Helper to add base class methods to the derived class one (this covers the 'using' cases...
TFunctionTemplate * GetFunctionTemplate(const char *name)
TClass * GetClass() const
TClassRef is used to implement a permanent reference to a TClass object.
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, Long_t)
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check=kTRUE)
Retrieve a linear buffer pointer from the given pyobject.
void * CreateWrapperMethod(PyObject *pyfunc, Long_t user, const char *retType, const std::vector< std::string > &signature, const char *callback)
Compile a function on the fly and return a function pointer for use on C-APIs.
Bool_t MethodProxy_Check(T *object)
Py_ssize_t ArraySize(const std::string &name)
Extract size from an array type, if available.
void ErrMsgCallback(char *msg)
Translate CINT error/warning into python equivalent.
TMethod * GetMethodAny(const char *method)
Return pointer to method without looking at parameters.
static Cppyy::TCppMethod_t FindAndAddOperator(const std::string &lcname, const std::string &rcname, const char *op, TClass *klass=0)
Helper to find a function with matching signature in 'funcs'.
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
const std::string Compound(const std::string &name)
Break down the compound of a fully qualified type name.