@@ -493,7 +493,7 @@ static inline PyObject* SelectAndForward(TemplateProxy* pytmpl, CPPOverload* pym
493493static inline PyObject* CallMethodImp (TemplateProxy* pytmpl, PyObject*& pymeth,
494494 CPyCppyy_PyArgs_t args, size_t nargsf, PyObject* kwds, bool impOK, uint64_t sighash)
495495{
496- // Actual call of a given overload: takes care of handling of "self" and
496+ // Actual call of a given overload: takes care of handlign of "self" and
497497// dereferences the overloaded method after use.
498498
499499 PyObject* result;
@@ -654,13 +654,13 @@ static PyObject* tpp_call(TemplateProxy* pytmpl, PyObject* args, PyObject* kwds)
654654 result = SelectAndForward (pytmpl, pytmpl->fTI ->fNonTemplated , args, nargsf, kwds,
655655 true /* implicitOkay */ , false /* use_targs */ , sighash, errors);
656656 if (result)
657- return result ;
657+ TPPCALL_RETURN ;
658658
659659// case 3: select known template overload
660660 result = SelectAndForward (pytmpl, pytmpl->fTI ->fTemplated , args, nargsf, kwds,
661661 false /* implicitOkay */ , true /* use_targs */ , sighash, errors);
662662 if (result)
663- return result ;
663+ TPPCALL_RETURN ;
664664
665665// case 4: auto-instantiation from types of arguments
666666 for (auto pref : {Utility::kReference , Utility::kPointer , Utility::kValue }) {
@@ -681,7 +681,7 @@ static PyObject* tpp_call(TemplateProxy* pytmpl, PyObject* args, PyObject* kwds)
681681 result = SelectAndForward (pytmpl, pytmpl->fTI ->fLowPriority , args, nargsf, kwds,
682682 false /* implicitOkay */ , false /* use_targs */ , sighash, errors);
683683 if (result)
684- return result ;
684+ TPPCALL_RETURN ;
685685
686686// error reporting is fraud, given the numerous steps taken, but more details seems better
687687 if (!errors.empty ()) {
@@ -790,20 +790,67 @@ static PyObject* tpp_overload(TemplateProxy* pytmpl, PyObject* args)
790790{
791791// Select and call a specific C++ overload, based on its signature.
792792 const char * sigarg = nullptr ;
793+ PyObject* sigarg_tuple = nullptr ;
793794 int want_const = -1 ;
794- if (!PyArg_ParseTuple (args, const_cast <char *>(" s|i:__overload__" ), &sigarg, &want_const))
795+
796+ Cppyy::TCppScope_t scope = (Cppyy::TCppScope_t) 0 ;
797+ Cppyy::TCppMethod_t cppmeth = (Cppyy::TCppMethod_t) 0 ;
798+ std::string proto;
799+
800+ if (PyArg_ParseTuple (args, const_cast <char *>(" s|i:__overload__" ), &sigarg, &want_const)) {
801+ want_const = PyTuple_GET_SIZE (args) == 1 ? -1 : want_const;
802+
803+ // check existing overloads in order
804+ PyObject* ol = pytmpl->fTI ->fNonTemplated ->FindOverload (sigarg, want_const);
805+ if (ol) return ol;
806+ PyErr_Clear ();
807+ ol = pytmpl->fTI ->fTemplated ->FindOverload (sigarg, want_const);
808+ if (ol) return ol;
809+ PyErr_Clear ();
810+ ol = pytmpl->fTI ->fLowPriority ->FindOverload (sigarg, want_const);
811+ if (ol) return ol;
812+
813+ proto = Utility::ConstructTemplateArgs (nullptr , args);
814+
815+ scope = ((CPPClass*)pytmpl->fTI ->fPyClass )->fCppType ;
816+ cppmeth = Cppyy::GetMethodTemplate (
817+ scope, pytmpl->fTI ->fCppName , proto.substr (1 , proto.size ()-2 ));
818+ } else if (PyArg_ParseTuple (args, const_cast <char *>(" O|i:__overload__" ), &sigarg_tuple, &want_const)) {
819+ PyErr_Clear ();
820+ want_const = PyTuple_GET_SIZE (args) == 1 ? -1 : want_const;
821+
822+ // check existing overloads in order
823+ PyObject* ol = pytmpl->fTI ->fNonTemplated ->FindOverload (sigarg_tuple, want_const);
824+ if (ol) return ol;
825+ PyErr_Clear ();
826+ ol = pytmpl->fTI ->fTemplated ->FindOverload (sigarg_tuple, want_const);
827+ if (ol) return ol;
828+ PyErr_Clear ();
829+ ol = pytmpl->fTI ->fLowPriority ->FindOverload (sigarg_tuple, want_const);
830+ if (ol) return ol;
831+
832+ proto.reserve (128 );
833+ proto.push_back (' <' );
834+ Py_ssize_t n = PyTuple_Size (sigarg_tuple);
835+ for (int i = 0 ; i < n; i++) {
836+ PyObject *pItem = PyTuple_GetItem (sigarg_tuple, i);
837+ if (!CPyCppyy_PyText_Check (pItem)) {
838+ PyErr_Format (PyExc_LookupError, " argument types should be in string format" );
839+ return (PyObject*) nullptr ;
840+ }
841+ proto.append (CPyCppyy_PyText_AsString (pItem));
842+ if (i < n - 1 )
843+ proto.push_back (' ,' );
844+ }
845+ proto.push_back (' >' );
846+
847+ scope = ((CPPClass*)pytmpl->fTI ->fPyClass )->fCppType ;
848+ cppmeth = Cppyy::GetMethodTemplate (
849+ scope, pytmpl->fTI ->fCppName , proto.substr (1 , proto.size ()-2 ));
850+ } else {
851+ PyErr_Format (PyExc_TypeError, " Unexpected arguments to __overload__" );
795852 return nullptr ;
796- want_const = PyTuple_GET_SIZE (args) == 1 ? -1 : want_const;
797-
798- // check existing overloads in order
799- PyObject* ol = pytmpl->fTI ->fNonTemplated ->FindOverload (sigarg, want_const);
800- if (ol) return ol;
801- PyErr_Clear ();
802- ol = pytmpl->fTI ->fTemplated ->FindOverload (sigarg, want_const);
803- if (ol) return ol;
804- PyErr_Clear ();
805- ol = pytmpl->fTI ->fLowPriority ->FindOverload (sigarg, want_const);
806- if (ol) return ol;
853+ }
807854
808855// else attempt instantiation
809856 PyObject* pytype = 0 , *pyvalue = 0 , *pytrace = 0 ;
@@ -877,7 +924,7 @@ PyTypeObject TemplateProxy_Type = {
877924#if PY_VERSION_HEX >= 0x03080000
878925 | Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_METHOD_DESCRIPTOR
879926#endif
880- , // tp_flags
927+ , // tp_flags
881928 (char *)" cppyy template proxy (internal)" , // tp_doc
882929 (traverseproc)tpp_traverse, // tp_traverse
883930 (inquiry)tpp_clear, // tp_clear
@@ -912,6 +959,12 @@ PyTypeObject TemplateProxy_Type = {
912959#if PY_VERSION_HEX >= 0x03040000
913960 , 0 // tp_finalize
914961#endif
962+ #if PY_VERSION_HEX >= 0x03080000
963+ , 0 // tp_vectorcall
964+ #endif
965+ #if PY_VERSION_HEX >= 0x030c0000
966+ , 0 // tp_watched
967+ #endif
915968};
916969
917970} // namespace CPyCppyy
0 commit comments