Main dispatch logic for calls to functions bound using pybind11
| 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 |
nothing calls this directly
no test coverage detected