37 for (
const auto&
c : p.second) {
47 bool isGreedy =
false;
68 fTI->fTemplated->AdoptMethod(pc);
76 std::string
proto =
"";
78#if PY_VERSION_HEX >= 0x03080000
91 PyObject* tpArgs = PyTuple_New(argc);
101 memset(&bufinfo, 0,
sizeof(Py_buffer));
103 if (PyObject_GetBuffer(itemi, &bufinfo, PyBUF_FORMAT) == 0) {
104 for (
int j = 0; j < bufinfo.ndim; ++j) ptrdef +=
"*";
105 PyBuffer_Release(&bufinfo);
113 PyTuple_SET_ITEM(tpArgs, i, pyptrname);
117 Py_DECREF(pytc); pytc =
nullptr;
124 if (!bArgSet && pytc) {
136 Py_XDECREF(pytc); pytc =
nullptr;
138 PyTuple_SET_ITEM(tpArgs, i, pyactname);
148 PyTuple_SET_ITEM(tpArgs, i, tmpl_name);
156 PyTuple_SET_ITEM(tpArgs, i, tp);
160#if PY_VERSION_HEX >= 0x03080000
161 PyObject* pyargs = PyTuple_New(argc);
165 PyTuple_SET_ITEM(pyargs, i, item);
171 const std::string& name_v1 = \
172 Utility::ConstructTemplateArgs(
nullptr, tpArgs, pyargs, pref, 0, pcnt);
179 if (PyErr_Occurred()) {
184 proto = name_v1.substr(1, name_v1.size()-2);
206 if (resname.find(
"initializer_list") != std::string::npos) {
207 auto pos =
proto.find(
"initializer_list");
208 while (pos != std::string::npos) {
209 proto.replace(pos, 16,
"vector");
210 pos =
proto.find(
"initializer_list", pos + 6);
214 if (m2 && m2 != cppmeth) {
222 bool bExactMatch = fname == resname;
227 PyObject* pyol = PyObject_GetItem(dct, pycachename);
228 if (!pyol) PyErr_Clear();
236 exact = PyObject_GetItem(dct, pyresname);
237 if (!exact) PyErr_Clear();
241 bool bIsConstructor =
false, bNeedsRebind =
true;
246 bNeedsRebind =
false;
249 bNeedsRebind =
false;
251 bIsConstructor =
true;
260 if (bIsConstructor) {
267 PyType_Type.tp_setattro(
fTI->fPyClass, pycachename, pyol);
294 if (!exact && !bExactMatch) {
295 PyType_Type.tp_setattro(
fTI->fPyClass, pyresname, pyol);
300 Py_DECREF(pyresname);
301 Py_DECREF(pycachename);
310 PyErr_Format(PyExc_TypeError,
"Failed to instantiate \"%s(%s)\"", fname.c_str(),
proto.c_str());
320 pytmpl->
fSelf =
nullptr;
324 pytmpl->
fTI = std::make_shared<TemplateInfo>();
326 PyObject_GC_Track(pytmpl);
339 if (op == Py_EQ || op == Py_NE) {
349 Py_INCREF(Py_NotImplemented);
350 return Py_NotImplemented;
357 Py_CLEAR(pytmpl->
fSelf);
368 PyObject_ClearWeakRefs((
PyObject*)pytmpl);
369 PyObject_GC_UnTrack(pytmpl);
371 pytmpl->
fTI.~TP_TInfo_t();
372 PyObject_GC_Del(pytmpl);
379 Py_VISIT(pytmpl->
fSelf);
388 if (pytmpl->
fTI->fDoc) {
389 Py_INCREF(pytmpl->
fTI->fDoc);
390 return pytmpl->
fTI->fDoc;
395 if (pytmpl->
fTI->fNonTemplated->HasMethods())
396 doc = PyObject_GetAttrString((
PyObject*)pytmpl->
fTI->fNonTemplated,
"__doc__");
397 if (pytmpl->
fTI->fTemplated->HasMethods()) {
402 }
else if (!doc && doc2) {
406 if (pytmpl->
fTI->fLowPriority->HasMethods()) {
411 }
else if (!doc && doc2) {
424 Py_XDECREF(pytmpl->
fTI->fDoc);
426 pytmpl->
fTI->fDoc = val;
434#define TPPCALL_RETURN \
448 bool bInserted =
false;
449 auto&
v = pytmpl->
fTI->fDispatchMap[use_targs ?
targs2str(pytmpl) :
""];
453 if (p.first == sighash) {
459 if (!bInserted)
v.push_back(std::make_pair(sighash, pymeth));
464 bool implicitOkay,
bool use_targs, uint64_t sighash, std::vector<Utility::PyError_t>& errors)
497 if (isNS && pytmpl->
fSelf && pytmpl->
fSelf != Py_None) {
513 Py_DECREF(pymeth); pymeth =
nullptr;
517#if PY_VERSION_HEX >= 0x03080000
519 TemplateProxy* pytmpl,
PyObject*
const *args,
size_t nargsf,
PyObject* kwds)
552#if PY_VERSION_HEX < 0x03080000
553 size_t nargsf = PyTuple_GET_SIZE(args);
556 PyObject *pymeth =
nullptr, *result =
nullptr;
565 auto&
v = pytmpl->
fTI->fDispatchMap[
""];
566 for (
const auto& p :
v) {
567 if (p.first == sighash) {
574 if (!pytmpl->
fSelf || pytmpl->
fSelf == Py_None) {
580 Py_DECREF(pymeth); pymeth =
nullptr;
588 std::vector<Utility::PyError_t> errors;
599 if (pytmpl->
fSelf && pytmpl->
fSelf != Py_None && !isNS)
600 pymeth = PyObject_GetAttr(pytmpl->
fSelf, pyfullname);
602 pymeth = PyType_Type.tp_getattro(pytmpl->
fTI->fPyClass, pyfullname);
607 result =
CallMethodImp(pytmpl, pymeth, args, nargsf, kwds,
true, sighash);
609 Py_DECREF(pyfullname);
613 }
else if (pymeth && PyCallable_Check(pymeth)) {
618 Py_DECREF(pyfullname);
630 result =
CallMethodImp(pytmpl, pymeth, args, nargsf, kwds,
true, sighash);
632 Py_DECREF(pyfullname);
641 Py_DECREF(pyfullname);
649 true ,
false , sighash, errors);
655 false ,
true , sighash, errors);
664 pymeth = pytmpl->
Instantiate(pytmpl->
fTI->fCppName, args, nargsf, pref, &pcnt);
667 result =
CallMethodImp(pytmpl, pymeth, args, nargsf, kwds,
true, sighash);
676 false ,
false , sighash, errors);
681 if (!errors.empty()) {
685 PyErr_Format(PyExc_TypeError,
"cannot resolve method template call for \'%s\'",
686 pytmpl->
fTI->fCppName.c_str());
701 newPyTmpl->
fSelf = pyobj;
704 newPyTmpl->
fSelf = Py_None;
711 new (&newPyTmpl->
fTI) std::shared_ptr<TemplateInfo>{pytmpl->
fTI};
713#if PY_VERSION_HEX >= 0x03080000
714 newPyTmpl->fVectorCall = pytmpl->fVectorCall;
733 if (PyErr_Occurred()) {
742 return PyInt_FromLong(0);
763 PyErr_SetString(PyExc_AttributeError,
"__template_args__ is read-only");
775 (
char*)
"unused",
nullptr},
777 (
char*)
"the template arguments for this method",
nullptr},
778 {(
char*)
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
789 fTI->fCppName = cppname;
791 fTI->fPyClass = pyclass;
793 std::vector<PyCallable*> dummy;
798#if PY_VERSION_HEX >= 0x03080000
799 fVectorCall = (vectorcallfunc)tpp_vectorcall;
808 const char* sigarg =
nullptr;
809 const char* tmplarg =
nullptr;
817 if (PyArg_ParseTuple(args,
const_cast<char*
>(
"s|i:__overload__"), &sigarg, &want_const)) {
818 want_const = PyTuple_GET_SIZE(args) == 1 ? -1 : want_const;
821 PyObject* ol = pytmpl->
fTI->fNonTemplated->FindOverload(sigarg, want_const);
824 ol = pytmpl->
fTI->fTemplated->FindOverload(sigarg, want_const);
827 ol = pytmpl->
fTI->fLowPriority->FindOverload(sigarg, want_const);
833 if (PyErr_Occurred()) {
837 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
839 scope, pytmpl->
fTI->fCppName,
proto.substr(1,
proto.size()-2));
840 }
else if (PyArg_ParseTuple(args,
const_cast<char*
>(
"ss:__overload__"), &sigarg, &tmplarg)) {
841 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
842 std::string full_name = std::string(pytmpl->
fTI->fCppName) +
"<" + tmplarg +
">";
845 }
else if (PyArg_ParseTuple(args,
const_cast<char*
>(
"O|i:__overload__"), &sigarg_tuple, &want_const)) {
847 want_const = PyTuple_GET_SIZE(args) == 1 ? -1 : want_const;
850 PyObject* ol = pytmpl->
fTI->fNonTemplated->FindOverload(sigarg_tuple, want_const);
853 ol = pytmpl->
fTI->fTemplated->FindOverload(sigarg_tuple, want_const);
856 ol = pytmpl->
fTI->fLowPriority->FindOverload(sigarg_tuple, want_const);
860 proto.push_back(
'<');
862 for (
int i = 0; i <
n; i++) {
863 PyObject *pItem = PyTuple_GetItem(sigarg_tuple, i);
865 PyErr_Format(PyExc_LookupError,
"argument types should be in string format");
870 proto.push_back(
',');
872 proto.push_back(
'>');
874 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
876 scope, pytmpl->
fTI->fCppName,
proto.substr(1,
proto.size()-2));
878 PyErr_Format(PyExc_TypeError,
"Unexpected arguments to __overload__");
904 {(
char*)
"__overload__", (PyCFunction)
tpp_overload, METH_VARARGS,
905 (
char*)
"select overload for dispatch" },
906 {(
char*)
nullptr,
nullptr, 0,
nullptr }
913 (
char*)
"cppyy.TemplateProxy",
917#
if PY_VERSION_HEX >= 0x03080000
930#
if PY_VERSION_HEX >= 0x03080000
931 (ternaryfunc)PyVectorcall_Call,
939 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
940#
if PY_VERSION_HEX >= 0x03080000
941 | Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_METHOD_DESCRIPTOR
944 (
char*)
"cppyy template proxy (internal)",
969#if PY_VERSION_HEX >= 0x02030000
972#if PY_VERSION_HEX >= 0x02060000
975#if PY_VERSION_HEX >= 0x03040000
978#if PY_VERSION_HEX >= 0x03080000
981#if PY_VERSION_HEX >= 0x030c0000
984#if PY_VERSION_HEX >= 0x030d0000
#define CPyCppyy_PyText_InternFromString
#define CPyCppyy_PyText_Append
#define CPyCppyy_PyText_AsString
static Py_ssize_t CPyCppyy_PyArgs_GET_SIZE(CPyCppyy_PyArgs_t args, size_t)
PyObject * CPyCppyy_PyArgs_t
#define CPyCppyy_PyText_AppendAndDel
PyObject * CPyCppyy_PyObject_Call(PyObject *cb, PyObject *args, size_t, PyObject *kwds)
#define CPyCppyy_PyText_FromFormat
PyObject * CPyCppyy_tp_call(PyObject *cb, PyObject *args, size_t, PyObject *kwds)
#define CPyCppyy_PyText_FromString
static PyObject * CPyCppyy_PyArgs_GET_ITEM(CPyCppyy_PyArgs_t args, Py_ssize_t i)
#define CPyCppyy_PyText_Check
#define PyVarObject_HEAD_INIT(type, size)
void MergeOverload(CPPOverload *meth)
void AdoptMethod(PyCallable *pc)
MethodInfo_t * fMethodInfo
virtual PyCallable * Clone()=0
virtual bool IsGreedy()=0
CPPOverload * fLowPriority
TP_DispatchMap_t fDispatchMap
CPPOverload * fNonTemplated
PyObject * Instantiate(const std::string &fname, CPyCppyy_PyArgs_t tmplArgs, size_t nargsf, Utility::ArgPreference, int *pcnt=nullptr)
void Set(const std::string &cppname, const std::string &pyname, PyObject *pyclass)
PyObject_HEAD PyObject * fSelf
void AdoptTemplate(PyCallable *pc)
void AdoptMethod(PyCallable *pc)
void MergeOverload(CPPOverload *mp)
PyObject * CT2CppName(PyObject *pytc, const char *cpd, bool allow_voidp)
void SetDetailedException(std::vector< PyError_t > &&errors, PyObject *topmsg, PyObject *defexc)
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
size_t FetchError(std::vector< PyError_t > &, bool is_cpp=false)
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
static PyObject * tpp_richcompare(TemplateProxy *self, PyObject *other, int op)
bool AdjustSelf(PyCallArgs &cargs)
static PyObject * tpp_doc(TemplateProxy *pytmpl, void *)
static PyMappingMethods tpp_as_mapping
bool CPPOverload_Check(T *object)
static int tpp_clear(TemplateProxy *pytmpl)
static PyObject * tpp_call(TemplateProxy *pytmpl, PyObject *args, PyObject *kwds)
static PyObject * tpp_getuseffi(CPPOverload *, void *)
bool TemplateProxy_CheckExact(T *object)
static void tpp_dealloc(TemplateProxy *pytmpl)
uint64_t HashSignature(CPyCppyy_PyArgs_t args, size_t nargsf)
static int tpp_traverse(TemplateProxy *pytmpl, visitproc visit, void *arg)
static PyObject * tpp_overload(TemplateProxy *pytmpl, PyObject *args)
static int tpp_setuseffi(CPPOverload *, PyObject *, void *)
static PyGetSetDef tpp_getset[]
PyTypeObject CPPOverload_Type
PyTypeObject TemplateProxy_Type
static PyObject * tpp_subscript(TemplateProxy *pytmpl, PyObject *args)
static PyObject * CallMethodImp(TemplateProxy *pytmpl, PyObject *&pymeth, CPyCppyy_PyArgs_t args, size_t nargsf, PyObject *kwds, bool impOK, uint64_t sighash)
static void UpdateDispatchMap(TemplateProxy *pytmpl, bool use_targs, uint64_t sighash, CPPOverload *pymeth)
static int tpp_settemplateargs(TemplateProxy *, PyObject *, void *)
static TemplateProxy * tpp_new(PyTypeObject *, PyObject *, PyObject *)
static PyMethodDef tpp_methods[]
static int tpp_doc_set(TemplateProxy *pytmpl, PyObject *val, void *)
static Py_hash_t tpp_hash(TemplateProxy *self)
static PyObject * SelectAndForward(TemplateProxy *pytmpl, CPPOverload *pymeth, CPyCppyy_PyArgs_t args, size_t nargsf, PyObject *kwds, bool implicitOkay, bool use_targs, uint64_t sighash, std::vector< Utility::PyError_t > &errors)
static std::string targs2str(TemplateProxy *pytmpl)
static TemplateProxy * tpp_descr_get(TemplateProxy *pytmpl, PyObject *pyobj, PyObject *)
static PyObject * tpp_gettemplateargs(TemplateProxy *self, void *)
bool TemplateProxy_Check(T *object)
std::shared_ptr< TemplateInfo > TP_TInfo_t
RPY_EXPORTED TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
RPY_EXPORTED bool IsConstructor(TCppMethod_t method)
RPY_EXPORTED bool IsNamespace(TCppScope_t scope)
RPY_EXPORTED bool IsStaticMethod(TCppMethod_t method)
RPY_EXPORTED bool IsStaticTemplate(TCppScope_t scope, const std::string &name)
RPY_EXPORTED std::string GetMethodFullName(TCppMethod_t)
CPPOverload::Methods_t fMethods