diff --git a/bindings/pyroot/src/MethodHolder.cxx b/bindings/pyroot/src/MethodHolder.cxx index cec80cb1f247bb575770673dc7139b6a36170f21..b34cd78e16f8de207642ed57bdf7280ceb375cba 100644 --- a/bindings/pyroot/src/MethodHolder.cxx +++ b/bindings/pyroot/src/MethodHolder.cxx @@ -85,8 +85,8 @@ inline void PyROOT::TMethodHolder< T, M >::Destroy_() const template< class T, class M > inline PyObject* PyROOT::TMethodHolder< T, M >::CallFast( void* self ) { -// helper code to prevent some duplication; this is called from CallSafe() as well -// as directly from TMethodHolder::Execute in fast mode +// Helper code to prevent some duplication; this is called from CallSafe() as well +// as directly from TMethodHolder::Execute in fast mode. PyObject* result = 0; @@ -109,8 +109,8 @@ inline PyObject* PyROOT::TMethodHolder< T, M >::CallFast( void* self ) template< class T, class M > inline PyObject* PyROOT::TMethodHolder< T, M >::CallSafe( void* self ) { -// helper code to prevent some code duplication; this code embeds a ROOT "try/catch" -// block that saves the stack for restoration in case of an otherwise fatal signal +// Helper code to prevent some code duplication; this code embeds a ROOT "try/catch" +// block that saves the stack for restoration in case of an otherwise fatal signal. PyObject* result = 0; diff --git a/bindings/pyroot/src/Pythonize.cxx b/bindings/pyroot/src/Pythonize.cxx index f592f709767c5800e08bf05abf9d601c6e91027d..95e2b83305fc9cd9f546cdc1ab3326dd636fb6cb 100644 --- a/bindings/pyroot/src/Pythonize.cxx +++ b/bindings/pyroot/src/Pythonize.cxx @@ -63,6 +63,7 @@ namespace { //____________________________________________________________________________ inline Bool_t IsTemplatedSTLClass( const std::string& name, const std::string& klass ) { + // Scan the name of the class and determine whether it is a template instantiation. const int nsize = (int)name.size(); const int ksize = (int)klass.size(); @@ -74,6 +75,7 @@ namespace { // to prevent compiler warnings about const char* -> char* inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth ) { + // Helper; call method with signature: obj->meth(). Py_INCREF( obj ); PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "" ) ); Py_DECREF( obj ); @@ -83,7 +85,7 @@ namespace { //____________________________________________________________________________ inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1 ) { - // Helper; call method with signature: meth( pyobj ). + // Helper; call method with signature: obj->meth( arg1 ). Py_INCREF( obj ); PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "O" ), arg1 ); @@ -95,7 +97,7 @@ namespace { inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, PyObject* arg2 ) { - // Helper; call method with signature: meth( pyobj, pyobj ). + // Helper; call method with signature: obj->meth( arg1, arg2 ). Py_INCREF( obj ); PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "OO" ), arg1, arg2 ); @@ -106,7 +108,7 @@ namespace { //____________________________________________________________________________ inline PyObject* CallPyObjMethod( PyObject* obj, const char* meth, PyObject* arg1, int arg2 ) { - // Helper; call method with signature: meth( pyobj, int ). + // Helper; call method with signature: obj->meth( arg1, int ). Py_INCREF( obj ); PyObject* result = PyObject_CallMethod( obj, const_cast< char* >( meth ), const_cast< char* >( "Oi" ), arg1, arg2 ); @@ -998,6 +1000,7 @@ static int PyObject_Compare( PyObject* one, PyObject* other ) { //____________________________________________________________________________ PyObject* TObjStringLength( PyObject* self ) { + // Implementation of python __len__ for TObjString. PyObject* data = CallPyObjMethod( self, "GetName" ); Py_ssize_t size = PySequence_Size( data ); Py_DECREF( data ); @@ -1008,6 +1011,7 @@ static int PyObject_Compare( PyObject* one, PyObject* other ) { //- TIter behavior ------------------------------------------------------------- PyObject* TIterIter( PyObject* self ) { + // Implementation of python __iter__ (iterator protocol) for TIter. Py_INCREF( self ); return self; } @@ -1015,6 +1019,7 @@ static int PyObject_Compare( PyObject* one, PyObject* other ) { //____________________________________________________________________________ PyObject* TIterNext( PyObject* self ) { + // Implementation of python __next__ (iterator protocol) for TIter. PyObject* next = CallPyObjMethod( self, "Next" ); if ( ! next ) @@ -1924,6 +1929,8 @@ namespace { //- public functions ----------------------------------------------------------- Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name ) { +// Add pre-defined pythonizations (for STL and ROOT) to classes based on their +// signature and/or class name. if ( pyclass == 0 ) return kFALSE; diff --git a/bindings/pyroot/src/RootModule.cxx b/bindings/pyroot/src/RootModule.cxx index e23c08fdbec93d127e4d78ec564752db651ffb1d..d55e87a75de1983fe07124800a147b2083b403af 100644 --- a/bindings/pyroot/src/RootModule.cxx +++ b/bindings/pyroot/src/RootModule.cxx @@ -42,6 +42,7 @@ namespace { //____________________________________________________________________________ PyObject* LookupRootEntity( PyObject* pyname, PyObject* args ) { + // Find a match within the ROOT module for something with name 'pyname'. const char* cname = 0; if ( pyname && PyROOT_PyUnicode_CheckExact( pyname ) ) cname = PyROOT_PyUnicode_AsString( pyname ); @@ -490,6 +491,7 @@ extern "C" PyObject* PyInit_libPyROOT() extern "C" void initlibPyROOT() #endif { +// Initialization of extension module libPyROOT. using namespace PyROOT; // load commonly used python strings diff --git a/bindings/pyroot/src/RootWrapper.cxx b/bindings/pyroot/src/RootWrapper.cxx index e7054adb76301bb527437c391efd987902f14555..d85e3da2052cbb3e4c1fa505931f2cc67786fbb5 100644 --- a/bindings/pyroot/src/RootWrapper.cxx +++ b/bindings/pyroot/src/RootWrapper.cxx @@ -63,6 +63,7 @@ namespace { // helper for creating new ROOT python types PyObject* CreateNewROOTPythonClass( const std::string& name, PyObject* pybases ) { + // Create a new python shadow class with the required hierarchy and meta-classes. Py_XINCREF( pybases ); if ( ! pybases ) { pybases = PyTuple_New( 1 ); @@ -101,6 +102,7 @@ namespace { // helper to split between CINT and Reflex Long_t GetDataMemberAddress( TClass* klass, TDataMember* mb ) { + // Get the address of a data member (CINT-style). Long_t offset = 0; G__DataMemberInfo dmi = ((G__ClassInfo*)klass->GetClassInfo())->GetDataMember( mb->GetName(), &offset ); return dmi.Offset(); @@ -109,6 +111,7 @@ namespace { #ifdef PYROOT_USE_REFLEX Long_t GetDataMemberAddress( const ROOT::Reflex::Scope&, const ROOT::Reflex::Member& mb ) { + // Get the address of a data member (Reflex-style). return (Long_t)mb.Offset(); } #endif @@ -121,6 +124,8 @@ namespace { inline void AddToGlobalScope( const char* label, TObject* obj, TClass* klass ) { + // Bind the given object with the given class in the global scope with the + // given label for its reference. PyModule_AddObject( gRootModule, const_cast< char* >( label ), PyROOT::BindRootObject( obj, klass ) ); } @@ -129,6 +134,7 @@ namespace { struct InitSTLTypes_t { InitSTLTypes_t() { + // Initialize the sets of known STL (container) types. std::string nss = "std::"; const char* stlTypes[] = { "complex", "exception", @@ -383,6 +389,7 @@ int PyROOT::BuildRootClassDict( const T& klass, PyObject* pyclass ) { template< class T, class B, class M > PyObject* PyROOT::BuildRootClassBases( const T& klass ) { +// Build a tuple of python shadow classes of all the bases of the given 'klass'. size_t nbases = klass.BaseSize(); // collect bases while removing duplicates @@ -432,6 +439,7 @@ template PyObject* PyROOT::BuildRootClassBases< \ //____________________________________________________________________________ PyObject* PyROOT::MakeRootClass( PyObject*, PyObject* args ) { +// Build a python shadow class for the given ROOT class. std::string cname = PyROOT_PyUnicode_AsString( PyTuple_GetItem( args, 0 ) ); if ( PyErr_Occurred() ) @@ -443,6 +451,8 @@ PyObject* PyROOT::MakeRootClass( PyObject*, PyObject* args ) //____________________________________________________________________________ PyObject* PyROOT::MakeRootClassFromType( TClass* klass ) { +// Build a python shadow class for the given ROOT class. + // locate class by full name, if possible to prevent parsing scopes/templates anew PyClassMap_t::iterator pci = gPyClasses.find( (void*)klass ); if ( pci != gPyClasses.end() ) { diff --git a/bindings/pyroot/src/TPyClassGenerator.cxx b/bindings/pyroot/src/TPyClassGenerator.cxx index c01b41d657da47af72013765f86dc3bcb489bf74..282f866808601883f7fbe492f2aad56d13dddf06 100644 --- a/bindings/pyroot/src/TPyClassGenerator.cxx +++ b/bindings/pyroot/src/TPyClassGenerator.cxx @@ -24,6 +24,7 @@ namespace { //_________________________________________________________________________ int PyCtorCallback( G__value* res, G__CONST char*, struct G__param*, int ) { + // CINT-installable constructor callback. int tagnum = G__value_get_tagnum( res ); PyObject* pyclass = PyROOT::Utility::GetInstalledMethod( tagnum ); if ( ! pyclass ) @@ -45,6 +46,7 @@ namespace { //_________________________________________________________________________ int PyMemFuncCallback( G__value* res, G__CONST char*, struct G__param* libp, int ) { + // CINT-installable member function callback. PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) ); if ( ! pyfunc ) return 0; @@ -130,13 +132,16 @@ namespace { //- public members ----------------------------------------------------------- TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load ) { +// Just forward. return GetClass( name, load, kFALSE ); } //- public members ----------------------------------------------------------- TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silent ) { - // called if all other class generators failed, attempt to build from python class +// Class generator to make python classes available to CINT. + +// called if all other class generators failed, attempt to build from python class if ( PyROOT::gDictLookupActive == kTRUE ) return 0; // call originated from python @@ -237,12 +242,13 @@ TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silen //____________________________________________________________________________ TClass* TPyClassGenerator::GetClass( const type_info& typeinfo, Bool_t load, Bool_t silent ) { +// Just forward; based on type name only. return GetClass( typeinfo.name(), load, silent ); } //____________________________________________________________________________ TClass* TPyClassGenerator::GetClass( const type_info& typeinfo, Bool_t load ) { -// just forward, based on name only +// Just forward; based on type name only return GetClass( typeinfo.name(), load ); } diff --git a/bindings/pyroot/src/TPySelector.cxx b/bindings/pyroot/src/TPySelector.cxx index 5dfb3b8d8c0df2f43b687b5927ffdee98e20656c..cdf390e796170e28179cddbb4a24bd3523f341c9 100644 --- a/bindings/pyroot/src/TPySelector.cxx +++ b/bindings/pyroot/src/TPySelector.cxx @@ -68,6 +68,7 @@ ClassImp(TPySelector) //- private helpers ---------------------------------------------------------- void TPySelector::SetupPySelf() { +// Install the python side identity of the TPySelector. if ( fPySelf && fPySelf != Py_None ) return; // already created ... diff --git a/bindings/pyroot/src/Utility.cxx b/bindings/pyroot/src/Utility.cxx index 2ffc0f95911deef65f71949cb8b2cfd5fae88486..342062343fe818094867f8a5d25a080224fccb19 100644 --- a/bindings/pyroot/src/Utility.cxx +++ b/bindings/pyroot/src/Utility.cxx @@ -54,6 +54,8 @@ namespace { struct InitOperatorMapping_t { public: InitOperatorMapping_t() { + // Initialize the global map of operator names C++ -> python. + // gC2POperatorMapping[ "[]" ] = "__setitem__"; // depends on return type // gC2POperatorMapping[ "+" ] = "__add__"; // depends on # of args (see __pos__) // gC2POperatorMapping[ "-" ] = "__sub__"; // id. (eq. __neg__) @@ -127,7 +129,7 @@ namespace { //- public functions --------------------------------------------------------- ULong_t PyROOT::PyLongOrInt_AsULong( PyObject* pyobject ) { -// convert <pybject> to C++ unsigned long, with bounds checking, allow int -> ulong +// Convert <pybject> to C++ unsigned long, with bounds checking, allow int -> ulong. ULong_t ul = PyLong_AsUnsignedLong( pyobject ); if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) { PyErr_Clear(); @@ -146,7 +148,7 @@ ULong_t PyROOT::PyLongOrInt_AsULong( PyObject* pyobject ) //____________________________________________________________________________ ULong64_t PyROOT::PyLongOrInt_AsULong64( PyObject* pyobject ) { -// convert <pyobject> to C++ unsigned long long, with bounds checking +// Convert <pyobject> to C++ unsigned long long, with bounds checking. ULong64_t ull = PyLong_AsUnsignedLongLong( pyobject ); if ( PyErr_Occurred() && PyInt_Check( pyobject ) ) { PyErr_Clear(); @@ -165,6 +167,8 @@ ULong64_t PyROOT::PyLongOrInt_AsULong64( PyObject* pyobject ) //____________________________________________________________________________ Bool_t PyROOT::Utility::SetMemoryPolicy( EMemoryPolicy e ) { +// Set the global memory policy, which affects object ownership when objects +// are passed as function arguments. if ( kHeuristics <= e && e <= kStrict ) { gMemoryPolicy = e; return kTRUE; @@ -175,6 +179,8 @@ Bool_t PyROOT::Utility::SetMemoryPolicy( EMemoryPolicy e ) //____________________________________________________________________________ Bool_t PyROOT::Utility::SetSignalPolicy( ESignalPolicy e ) { +// Set the global signal policy, which determines whether a jmp address +// should be saved to return to after a C++ segfault. if ( kFast <= e && e <= kSafe ) { gSignalPolicy = e; return kTRUE; @@ -186,6 +192,8 @@ Bool_t PyROOT::Utility::SetSignalPolicy( ESignalPolicy e ) Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, PyCFunction cfunc, int flags ) { +// Add the given function to the class under name 'label'. + // use list for clean-up (.so's are unloaded only at interpreter shutdown) static std::list< PyMethodDef > s_pymeths; @@ -216,6 +224,7 @@ Bool_t PyROOT::Utility::AddToClass( //____________________________________________________________________________ Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, const char* func ) { +// Add the given function to the class under name 'label'. PyObject* pyfunc = PyObject_GetAttrString( pyclass, const_cast< char* >( func ) ); if ( ! pyfunc ) return kFALSE; @@ -229,6 +238,7 @@ Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, const //____________________________________________________________________________ Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, PyCallable* pyfunc ) { +// Add the given function to the class under name 'label'. MethodProxy* method = (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( label ) ); @@ -252,8 +262,8 @@ Bool_t PyROOT::Utility::AddToClass( PyObject* pyclass, const char* label, PyCall //____________________________________________________________________________ Bool_t PyROOT::Utility::AddUsingToClass( PyObject* pyclass, const char* method ) { -// helper to add base class methods to the derived class one (this covers the -// 'using' cases, which the dictionary does not provide) +// Helper to add base class methods to the derived class one (this covers the +// 'using' cases, which the dictionary does not provide). MethodProxy* derivedMethod = (MethodProxy*)PyObject_GetAttrString( pyclass, const_cast< char* >( method ) ); @@ -306,9 +316,9 @@ Bool_t PyROOT::Utility::AddUsingToClass( PyObject* pyclass, const char* method ) Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* left, PyObject* right, const char* op, const char* label ) { -// install the named operator (op) into the left object's class if such a function +// Install the named operator (op) into the left object's class if such a function // exists as a global overload; a label must be given if the operator is not in -// gC2POperatorMapping (i.e. if it is ambiguous at the member level) +// gC2POperatorMapping (i.e. if it is ambiguous at the member level). // this should be a given, nevertheless ... if ( ! ObjectProxy_Check( left ) ) @@ -328,7 +338,7 @@ Bool_t PyROOT::Utility::AddBinaryOperator( //____________________________________________________________________________ Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const char* op, const char* label ) { -// install binary operator op in pyclass, working on two instances of pyclass +// Install binary operator op in pyclass, working on two instances of pyclass. PyObject* pyname = PyObject_GetAttr( pyclass, PyStrings::gName ); std::string cname = ResolveTypedef( PyROOT_PyUnicode_AsString( pyname ) ); Py_DECREF( pyname ); pyname = 0; @@ -339,7 +349,7 @@ Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const char* op, co //____________________________________________________________________________ static inline TFunction* FindAndAddOperator( const std::string& lcname, const std::string& rcname, const char* op, TCollection* funcs ) { -// helper to find a function with matching signature in 'funcs' +// Helper to find a function with matching signature in 'funcs'. std::string opname = "operator"; opname += op; @@ -369,9 +379,9 @@ static inline TFunction* FindAndAddOperator( const std::string& lcname, const st Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string& lcname, const std::string& rcname, const char* op, const char* label ) { -// find a global function with a matching signature and install the result on pyclass; +// Find a global function with a matching signature and install the result on pyclass; // in addition, __gnu_cxx is searched pro-actively (as there's AFAICS no way to unearth -// using information) +// using information). static TClassRef gnucxx( "__gnu_cxx" ); TFunction* func = 0; @@ -399,9 +409,9 @@ Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string& //____________________________________________________________________________ Bool_t PyROOT::Utility::BuildTemplateName( PyObject*& pyname, PyObject* args, int argoff ) { -// helper to construct the "< type, type, ... >" part of a templated name (either +// Helper to construct the "< type, type, ... >" part of a templated name (either // for a class as in MakeRootTemplateClass in RootModule.cxx) or for method lookup -// (as in TemplatedMemberHook, below) +// (as in TemplatedMemberHook, below). PyROOT_PyUnicode_AppendAndDel( &pyname, PyROOT_PyUnicode_FromString( "<" ) ); @@ -449,6 +459,8 @@ Bool_t PyROOT::Utility::BuildTemplateName( PyObject*& pyname, PyObject* args, in //____________________________________________________________________________ Bool_t PyROOT::Utility::InitProxy( PyObject* module, PyTypeObject* pytype, const char* name ) { +// Initialize a proxy class for use by python, and add it to the ROOT module. + // finalize proxy type if ( PyType_Ready( pytype ) < 0 ) return kFALSE; @@ -467,6 +479,8 @@ Bool_t PyROOT::Utility::InitProxy( PyObject* module, PyTypeObject* pytype, const //____________________________________________________________________________ int PyROOT::Utility::GetBuffer( PyObject* pyobject, char tc, int size, void*& buf, Bool_t check ) { +// Retrieve a linear buffer pointer from the given pyobject. + // special case: don't handle character strings here (yes, they're buffers, but not quite) if ( PyBytes_Check( pyobject ) ) return 0; @@ -533,7 +547,7 @@ int PyROOT::Utility::GetBuffer( PyObject* pyobject, char tc, int size, void*& bu //____________________________________________________________________________ std::string PyROOT::Utility::MapOperatorName( const std::string& name, Bool_t bTakesParams ) { -// map the given C++ operator name on the python equivalent +// Map the given C++ operator name on the python equivalent. if ( 8 < name.size() && name.substr( 0, 8 ) == "operator" ) { std::string op = name.substr( 8, std::string::npos ); @@ -579,6 +593,7 @@ std::string PyROOT::Utility::MapOperatorName( const std::string& name, Bool_t bT //____________________________________________________________________________ PyROOT::Utility::EDataType PyROOT::Utility::EffectiveType( const std::string& name ) { +// Determine the actual type (to be used for types that are not classes). EDataType effType = kOther; G__TypeInfo ti( name.c_str() ); @@ -626,6 +641,7 @@ PyROOT::Utility::EDataType PyROOT::Utility::EffectiveType( const std::string& na //____________________________________________________________________________ const std::string PyROOT::Utility::Compound( const std::string& name ) { +// Break down the compound of a fully qualified type name. std::string cleanName = name; std::string::size_type spos = std::string::npos; while ( ( spos = cleanName.find( "const" ) ) != std::string::npos ) { @@ -647,6 +663,8 @@ const std::string PyROOT::Utility::Compound( const std::string& name ) //____________________________________________________________________________ const std::string PyROOT::Utility::ClassName( PyObject* pyobj ) { +// Retrieve the class name from the given python object (which may be just an +// instance of the class). std::string clname = "<unknown>"; PyObject* pyclass = PyObject_GetAttr( pyobj, PyStrings::gClass ); if ( pyclass != 0 ) { @@ -668,6 +686,8 @@ const std::string PyROOT::Utility::ClassName( PyObject* pyobj ) //____________________________________________________________________________ const std::string PyROOT::Utility::ResolveTypedef( const std::string& typeName ) { +// Helper; captures common code needed to find the real class name underlying +// a typedef (if any). G__TypeInfo ti( typeName.c_str() ); if ( ! ti.IsValid() ) return typeName; @@ -679,7 +699,7 @@ const std::string PyROOT::Utility::ResolveTypedef( const std::string& typeName ) //____________________________________________________________________________ void PyROOT::Utility::ErrMsgCallback( char* msg ) { -// Translate CINT error/warning into python equivalent +// Translate CINT error/warning into python equivalent. // ignore the "*** Interpreter error recovered ***" message if ( strstr( msg, "error recovered" ) ) @@ -749,7 +769,7 @@ void PyROOT::Utility::ErrMsgCallback( char* msg ) //____________________________________________________________________________ void PyROOT::Utility::ErrMsgHandler( int level, Bool_t abort, const char* location, const char* msg ) { -// Translate ROOT error/warning to python +// Translate ROOT error/warning to python. // initialization from gEnv (the default handler will return w/o msg b/c level too low) if ( gErrorIgnoreLevel == kUnset ) @@ -775,6 +795,7 @@ Long_t PyROOT::Utility::InstallMethod( G__ClassInfo* scope, PyObject* callback, const std::string& mtName, const char* rtype, const char* signature, void* func, Int_t npar, Long_t extra ) { +// Install the given CINT-based method (typically callbacks). static Long_t s_fid = (Long_t)PyROOT::Utility::InstallMethod; ++s_fid; @@ -840,7 +861,7 @@ Long_t PyROOT::Utility::InstallMethod( G__ClassInfo* scope, PyObject* callback, //____________________________________________________________________________ PyObject* PyROOT::Utility::GetInstalledMethod( int tagnum, Long_t* extra ) { -// Return the CINT-installed python callable, if any +// Return the CINT-installed python callable, if any. CallInfo_t cinfo = s_PyObjectCallbacks[ tagnum ]; if ( extra ) *extra = cinfo.second; @@ -850,9 +871,9 @@ PyObject* PyROOT::Utility::GetInstalledMethod( int tagnum, Long_t* extra ) //____________________________________________________________________________ PyObject* PyROOT::Utility::PyErr_Occurred_WithGIL() { -// re-acquire the GIL before calling PyErr_Occurred() in case it has been +// Re-acquire the GIL before calling PyErr_Occurred() in case it has been // released; note that the p2.2 code assumes that there are no callbacks in -// C++ to python (or at least none returning errors) +// C++ to python (or at least none returning errors). #if PY_VERSION_HEX >= 0x02030000 PyGILState_STATE gstate = PyGILState_Ensure(); PyObject* e = PyErr_Occurred();