@@ -115,9 +115,9 @@ namespace {
115115 gC2POperatorMapping [" =" ] = " __assign__" ; // id.
116116
117117#if PY_VERSION_HEX < 0x03000000
118- gC2POperatorMapping [" bool" ] = " __nonzero__ " ;
118+ gC2POperatorMapping [" bool" ] = " __cpp_nonzero__ " ;
119119#else
120- gC2POperatorMapping [" bool" ] = " __bool__ " ;
120+ gC2POperatorMapping [" bool" ] = " __cpp_bool__ " ;
121121#endif
122122 }
123123 } initOperatorMapping_;
@@ -386,6 +386,22 @@ CPyCppyy::PyCallable* CPyCppyy::Utility::FindBinaryOperator(
386386}
387387
388388// ----------------------------------------------------------------------------
389+ static inline std::string AnnotationAsText (PyObject* pyobj)
390+ {
391+ if (!CPyCppyy_PyText_Check (pyobj)) {
392+ PyObject* pystr = PyObject_GetAttr (pyobj, CPyCppyy::PyStrings::gName );
393+ if (!pystr) {
394+ PyErr_Clear ();
395+ pystr = PyObject_Str (pyobj);
396+ }
397+
398+ std::string str = CPyCppyy_PyText_AsString (pystr);
399+ Py_DECREF (pystr);
400+ return str;
401+ }
402+ return CPyCppyy_PyText_AsString (pyobj);
403+ }
404+
389405static bool AddTypeName (std::string& tmpl_name, PyObject* tn, PyObject* arg,
390406 CPyCppyy::Utility::ArgPreference pref, int * pcnt = nullptr )
391407{
@@ -510,14 +526,14 @@ static bool AddTypeName(std::string& tmpl_name, PyObject* tn, PyObject* arg,
510526 if (ret) {
511527 // dict is ordered, with the last value being the return type
512528 std::ostringstream tpn;
513- tpn << (CPPScope_Check (ret) ? ClassName (ret) : CPyCppyy_PyText_AsString (ret))
529+ tpn << (CPPScope_Check (ret) ? ClassName (ret) : AnnotationAsText (ret))
514530 << " (*)(" ;
515531
516532 PyObject* values = PyDict_Values (annot);
517533 for (Py_ssize_t i = 0 ; i < (PyList_GET_SIZE (values)-1 ); ++i) {
518534 if (i) tpn << " , " ;
519535 PyObject* item = PyList_GET_ITEM (values, i);
520- tpn << (CPPScope_Check (item) ? ClassName (item) : CPyCppyy_PyText_AsString (item));
536+ tpn << (CPPScope_Check (item) ? ClassName (item) : AnnotationAsText (item));
521537 }
522538 Py_DECREF (values);
523539
@@ -587,7 +603,7 @@ std::string CPyCppyy::Utility::ConstructTemplateArgs(
587603 PyObject* tn = justOne ? tpArgs : PyTuple_GET_ITEM (tpArgs, i);
588604 if (CPyCppyy_PyText_Check (tn)) {
589605 tmpl_name.append (CPyCppyy_PyText_AsString (tn));
590- // some commmon numeric types (separated out for performance: checking for
606+ // some common numeric types (separated out for performance: checking for
591607 // __cpp_name__ and/or __name__ is rather expensive)
592608 } else {
593609 if (!AddTypeName (tmpl_name, tn, (args ? PyTuple_GET_ITEM (args, i) : nullptr ), pref, pcnt)) {
@@ -1039,14 +1055,18 @@ Py_ssize_t CPyCppyy::Utility::GetBuffer(PyObject* pyobject, char tc, int size, v
10391055
10401056// new-style buffer interface
10411057 if (PyObject_CheckBuffer (pyobject)) {
1058+ if (PySequence_Check (pyobject) && !PySequence_Size (pyobject))
1059+ return 0 ; // PyObject_GetBuffer() crashes on some platforms for some zero-sized seqeunces
1060+
10421061 Py_buffer bufinfo;
10431062 memset (&bufinfo, 0 , sizeof (Py_buffer));
10441063 if (PyObject_GetBuffer (pyobject, &bufinfo, PyBUF_FORMAT) == 0 ) {
10451064 if (tc == ' *' || strchr (bufinfo.format , tc)
1046- #ifdef _WIN32
1047- // ctypes is inconsistent in format on Windows; either way these types are the same size
1048- || (tc == ' I' && strchr (bufinfo.format , ' L' )) || (tc == ' i' && strchr (bufinfo.format , ' l' ))
1049- #endif
1065+ // if `long int` and `int` are the same size (on Windows and 32bit Linux,
1066+ // for example), `ctypes` isn't too picky about the type format, so make
1067+ // sure both integer types pass the type check
1068+ || (sizeof (long int ) == sizeof (int ) && ((tc == ' I' && strchr (bufinfo.format , ' L' )) ||
1069+ (tc == ' i' && strchr (bufinfo.format , ' l' ))))
10501070 // complex float is 'Zf' in bufinfo.format, but 'z' in single char
10511071 || (tc == ' z' && strstr (bufinfo.format , " Zf" ))
10521072 // allow 'signed char' ('b') from array to pass through '?' (bool as from struct)
@@ -1227,6 +1247,29 @@ std::string CPyCppyy::Utility::ClassName(PyObject* pyobj)
12271247 return clname;
12281248}
12291249
1250+ // ----------------------------------------------------------------------------
1251+ static std::set<std::string> sIteratorTypes ;
1252+ bool CPyCppyy::Utility::IsSTLIterator (const std::string& classname)
1253+ {
1254+ // attempt to recognize STL iterators (TODO: probably belongs in the backend)
1255+ if (sIteratorTypes .empty ()) {
1256+ std::string tt = " <int>::" ;
1257+ for (auto c : {" std::vector" , " std::list" , " std::deque" }) {
1258+ for (auto i : {" iterator" , " const_iterator" }) {
1259+ const std::string& itname = Cppyy::ResolveName (c+tt+i);
1260+ auto pos = itname.find (' <' );
1261+ if (pos != std::string::npos)
1262+ sIteratorTypes .insert (itname.substr (0 , pos));
1263+ }
1264+ }
1265+ }
1266+
1267+ auto pos = classname.find (' <' );
1268+ if (pos != std::string::npos)
1269+ return sIteratorTypes .find (classname.substr (0 , pos)) != sIteratorTypes .end ();
1270+ return false ;
1271+ }
1272+
12301273
12311274// ----------------------------------------------------------------------------
12321275CPyCppyy::Utility::PyOperators::~PyOperators ()
@@ -1284,23 +1327,17 @@ void CPyCppyy::Utility::SetDetailedException(std::vector<PyError_t>& errors, PyO
12841327 return ;
12851328 }
12861329
1287- // if a _single_ exception was from C++, assume it has priority
1288- PyObject* exc_type = nullptr ;
1330+ // if a _single_ exception was thrown from C++, assume it has priority (see below)
12891331 PyError_t* unique_from_cpp = nullptr ;
12901332 for (auto & e : errors) {
12911333 if (e.fIsCpp ) {
12921334 if (!unique_from_cpp)
12931335 unique_from_cpp = &e;
12941336 else {
1295- // two C++ exceptions, resort to default
1337+ // two C++ exceptions, resort to default behavior
12961338 unique_from_cpp = nullptr ;
1297- exc_type = defexc;
12981339 break ;
12991340 }
1300- } else if (!unique_from_cpp) {
1301- // try to consolidate Python exceptions, otherwise select default
1302- if (!exc_type) exc_type = e.fType ;
1303- else if (exc_type != e.fType ) exc_type = defexc;
13041341 }
13051342 }
13061343
@@ -1314,6 +1351,16 @@ void CPyCppyy::Utility::SetDetailedException(std::vector<PyError_t>& errors, PyO
13141351 Py_INCREF (unique_from_cpp->fType ); Py_INCREF (unique_from_cpp->fValue ); Py_XINCREF (unique_from_cpp->fTrace );
13151352 PyErr_Restore (unique_from_cpp->fType , unique_from_cpp->fValue , unique_from_cpp->fTrace );
13161353 } else {
1354+ // try to consolidate Python exceptions, otherwise select default
1355+ PyObject* exc_type = nullptr ;
1356+ for (auto & e : errors) {
1357+ if (!exc_type) exc_type = e.fType ;
1358+ else if (exc_type != e.fType ) {
1359+ exc_type = defexc;
1360+ break ;
1361+ }
1362+ }
1363+
13171364 // add the details to the topmsg
13181365 PyObject* separator = CPyCppyy_PyText_FromString (" \n " );
13191366 for (auto & e : errors) {
0 commit comments