MCPcopy Create free account
hub / github.com/pybind/pybind11 / dispatcher

Method dispatcher

include/pybind11/pybind11.h:940–1383  ·  view source on GitHub ↗

Main dispatch logic for calls to functions bound using pybind11

Source from the content-addressed store, hash-verified

938
939 /// Main dispatch logic for calls to functions bound using pybind11
940 static PyObject *
941 dispatcher(PyObject *self, PyObject *const *args_in_arr, size_t nargsf, PyObject *kwnames_in) {
942 using namespace detail;
943 const function_record *overloads = function_record_ptr_from_PyObject(self);
944 assert(overloads != nullptr);
945
946 /* Iterator over the list of potentially admissible overloads */
947 const function_record *current_overload = overloads;
948
949 /* Need to know how many arguments + keyword arguments there are to pick the right
950 overload */
951 const auto n_args_in = static_cast<size_t>(PyVectorcall_NARGS(nargsf));
952
953 handle parent = n_args_in > 0 ? args_in_arr[0] : nullptr,
954 result = PYBIND11_TRY_NEXT_OVERLOAD;
955
956 auto self_value_and_holder = value_and_holder();
957 if (overloads->is_constructor) {
958 if (!parent
959 || !PyObject_TypeCheck(parent.ptr(), (PyTypeObject *) overloads->scope.ptr())) {
960 set_error(PyExc_TypeError,
961 "__init__(self, ...) called with invalid or missing `self` argument");
962 return nullptr;
963 }
964
965 auto *const tinfo
966 = get_type_info(reinterpret_cast<PyTypeObject *>(overloads->scope.ptr()));
967 auto *const pi = reinterpret_cast<instance *>(parent.ptr());
968 self_value_and_holder = pi->get_value_and_holder(tinfo, true);
969
970 // If this value is already registered it must mean __init__ is invoked multiple times;
971 // we really can't support that in C++, so just ignore the second __init__.
972 if (self_value_and_holder.instance_registered()) {
973 return none().release().ptr();
974 }
975 }
976
977 try {
978 // We do this in two passes: in the first pass, we load arguments with `convert=false`;
979 // in the second, we allow conversion (except for arguments with an explicit
980 // py::arg().noconvert()). This lets us prefer calls without conversion, with
981 // conversion as a fallback.
982 std::vector<function_call> second_pass;
983
984 // However, if there are no overloads, we can just skip the no-convert pass entirely
985 const bool overloaded
986 = current_overload != nullptr && current_overload->next != nullptr;
987
988 for (; current_overload != nullptr; current_overload = current_overload->next) {
989
990 /* For each overload:
991 1. Copy all positional arguments we were given, also checking to make sure that
992 named positional arguments weren't *also* specified via kwarg.
993 2. If we weren't given enough, try to make up the omitted ones by checking
994 whether they were provided by a kwarg matching the `py::arg("name")` name. If
995 so, use it (and remove it from kwargs); if not, see if the function binding
996 provided a default that we can use.
997 3. Ensure that either all keyword arguments were "consumed", or that the

Callers

nothing calls this directly

Calls 15

noneClass · 0.85
tupleClass · 0.85
moveFunction · 0.85
try_translate_exceptionsFunction · 0.85
reprFunction · 0.85
raise_fromFunction · 0.85
ptrMethod · 0.80
get_value_and_holderMethod · 0.80
instance_registeredMethod · 0.80
releaseMethod · 0.80
emplace_backMethod · 0.80

Tested by

no test coverage detected