diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 556bdb7e34..e8742e2136 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -2171,21 +2171,75 @@ class argument_loader { /// Helper class which collects only positional arguments for a Python function call. /// A fancier version below can collect any argument, but this one is optimal for simple calls. -template +template class simple_collector { public: template - explicit simple_collector(Ts &&...values) - : m_args(pybind11::make_tuple(std::forward(values)...)) {} + explicit simple_collector(Ts &&...values) { + static_assert(sizeof...(Ts) == N, ""); + size_t i = 0; + using expander = int[]; + (void) expander{ + 0, + (m_args[i++] = detail::make_caster::cast(std::forward(values), policy, nullptr) + .inc_ref() + .ptr(), + 0)...}; + PYBIND11_WARNING_PUSH + PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits") + PYBIND11_WARNING_DISABLE_INTEL(186) + PYBIND11_WARNING_DISABLE_NVCC(186) + for (i = 0; i < N; ++i) { + if (!m_args[i]) { +#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) + throw cast_error_unable_to_convert_call_arg(std::to_string(i)); +#else + std::array argtypes{{type_id()...}}; + throw cast_error_unable_to_convert_call_arg(std::to_string(i), argtypes[i]); +#endif + } + } + PYBIND11_WARNING_POP + } - const tuple &args() const & { return m_args; } - dict kwargs() const { return {}; } + ~simple_collector() { + PYBIND11_WARNING_PUSH + PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits") + PYBIND11_WARNING_DISABLE_INTEL(186) + PYBIND11_WARNING_DISABLE_NVCC(186) + for (size_t i = 0; i < N; ++i) { + handle(m_args[i]).dec_ref(); + } + PYBIND11_WARNING_POP + } - tuple args() && { return std::move(m_args); } + simple_collector(const simple_collector &) = delete; + simple_collector(simple_collector &&) noexcept = default; + simple_collector &operator=(const simple_collector &) = delete; + simple_collector &operator=(simple_collector &&) noexcept = default; + + tuple args() const { + tuple result(N); + PYBIND11_WARNING_PUSH + PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits") + PYBIND11_WARNING_DISABLE_INTEL(186) + PYBIND11_WARNING_DISABLE_NVCC(186) + for (size_t i = 0; i < N; ++i) { + PyTuple_SET_ITEM(result.ptr(), i, handle(m_args[i]).inc_ref().ptr()); + } + PYBIND11_WARNING_POP + return result; + } + dict kwargs() const { return {}; } /// Call a Python function and pass the collected arguments object call(PyObject *ptr) const { - PyObject *result = PyObject_CallObject(ptr, m_args.ptr()); +#if PY_VERSION_HEX >= 0x03090000 + PyObject *result = PyObject_Vectorcall(ptr, m_args.data(), N, nullptr); +#else + // Use the old name for 3.8. + PyObject *result = _PyObject_Vectorcall(ptr, m_args.data(), N, nullptr); +#endif if (!result) { throw error_already_set(); } @@ -2193,7 +2247,7 @@ class simple_collector { } private: - tuple m_args; + std::array m_args; }; /// Helper class which collects positional, keyword, * and ** arguments for a Python function call @@ -2328,8 +2382,8 @@ constexpr bool args_are_all_positional() { template ()>> -simple_collector collect_arguments(Args &&...args) { - return simple_collector(std::forward(args)...); +simple_collector collect_arguments(Args &&...args) { + return simple_collector(std::forward(args)...); } /// Collect all arguments, including keywords and unpacking (only instantiated when needed) diff --git a/include/pybind11/detail/pybind11_namespace_macros.h b/include/pybind11/detail/pybind11_namespace_macros.h index 6f74bf85c7..40e18d4e67 100644 --- a/include/pybind11/detail/pybind11_namespace_macros.h +++ b/include/pybind11/detail/pybind11_namespace_macros.h @@ -62,6 +62,12 @@ # define PYBIND11_WARNING_DISABLE_INTEL(name) #endif +#ifdef __CUDACC__ +# define PYBIND11_WARNING_DISABLE_NVCC(name) PYBIND11_PRAGMA(nv_diag_suppress name) +#else +# define PYBIND11_WARNING_DISABLE_NVCC(name) +#endif + #define PYBIND11_NAMESPACE_BEGIN(name) \ namespace name { \ PYBIND11_WARNING_PUSH diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index cee4ab5623..7db4f98b78 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -1394,7 +1394,7 @@ template using is_keyword_or_ds = satisfies_any_of; // Call argument collector forward declarations -template +template class simple_collector; template class unpacking_collector;