diff options
Diffstat (limited to 'ext/pybind11/include/pybind11/attr.h')
-rw-r--r-- | ext/pybind11/include/pybind11/attr.h | 121 |
1 files changed, 94 insertions, 27 deletions
diff --git a/ext/pybind11/include/pybind11/attr.h b/ext/pybind11/include/pybind11/attr.h index e38a1a32d..dce875a6b 100644 --- a/ext/pybind11/include/pybind11/attr.h +++ b/ext/pybind11/include/pybind11/attr.h @@ -1,5 +1,5 @@ /* - pybind11/pybind11.h: Infrastructure for processing custom + pybind11/attr.h: Infrastructure for processing custom type and function attributes Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> @@ -12,7 +12,7 @@ #include "cast.h" -NAMESPACE_BEGIN(pybind11) +NAMESPACE_BEGIN(PYBIND11_NAMESPACE) /// \addtogroup annotations /// @{ @@ -58,15 +58,56 @@ struct metaclass { handle value; PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.") - metaclass() = default; + metaclass() {} /// Override pybind11's default metaclass explicit metaclass(handle value) : value(value) { } }; +/// Annotation that marks a class as local to the module: +struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } }; + /// Annotation to mark enums as an arithmetic type struct arithmetic { }; +/** \rst + A call policy which places one or more guard variables (``Ts...``) around the function call. + + For example, this definition: + + .. code-block:: cpp + + m.def("foo", foo, py::call_guard<T>()); + + is equivalent to the following pseudocode: + + .. code-block:: cpp + + m.def("foo", [](args...) { + T scope_guard; + return foo(args...); // forwarded arguments + }); + \endrst */ +template <typename... Ts> struct call_guard; + +template <> struct call_guard<> { using type = detail::void_type; }; + +template <typename T> +struct call_guard<T> { + static_assert(std::is_default_constructible<T>::value, + "The guard type must be default constructible"); + + using type = T; +}; + +template <typename T, typename... Ts> +struct call_guard<T, Ts...> { + struct type { + T guard{}; // Compose multiple guard types with left-to-right default-constructor order + typename call_guard<Ts...>::type next{}; + }; +}; + /// @} annotations NAMESPACE_BEGIN(detail) @@ -75,8 +116,6 @@ enum op_id : int; enum op_type : int; struct undefined_t; template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_; -template <typename... Args> struct init; -template <typename... Args> struct init_alias; inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret); /// Internal data structure which holds metadata about a keyword argument @@ -85,16 +124,17 @@ struct argument_record { const char *descr; ///< Human-readable version of the argument value handle value; ///< Associated Python object bool convert : 1; ///< True if the argument is allowed to convert when loading + bool none : 1; ///< True if None is allowed when loading - argument_record(const char *name, const char *descr, handle value, bool convert) - : name(name), descr(descr), value(value), convert(convert) { } + argument_record(const char *name, const char *descr, handle value, bool convert, bool none) + : name(name), descr(descr), value(value), convert(convert), none(none) { } }; /// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) struct function_record { function_record() - : is_constructor(false), is_stateless(false), is_operator(false), - has_args(false), has_kwargs(false), is_method(false) { } + : is_constructor(false), is_new_style_constructor(false), is_stateless(false), + is_operator(false), has_args(false), has_kwargs(false), is_method(false) { } /// Function name char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ @@ -123,6 +163,9 @@ struct function_record { /// True if name == '__init__' bool is_constructor : 1; + /// True if this is a new-style `__init__` defined in `detail/init.h` + bool is_new_style_constructor : 1; + /// True if this is a stateless function pointer bool is_stateless : 1; @@ -157,7 +200,7 @@ struct function_record { /// Special data structure which (temporarily) holds metadata about a bound class struct type_record { PYBIND11_NOINLINE type_record() - : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false) { } + : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false), module_local(false) { } /// Handle to the parent scope handle scope; @@ -171,17 +214,17 @@ struct type_record { /// How large is the underlying C++ type? size_t type_size = 0; - /// How large is pybind11::instance<type>? - size_t instance_size = 0; + /// How large is the type's holder? + size_t holder_size = 0; /// The global operator new can be overridden with a class-specific variant void *(*operator_new)(size_t) = ::operator new; - /// Function pointer to class_<..>::init_holder - void (*init_holder)(PyObject *, const void *) = nullptr; + /// Function pointer to class_<..>::init_instance + void (*init_instance)(instance *, const void *) = nullptr; /// Function pointer to class_<..>::dealloc - void (*dealloc)(PyObject *) = nullptr; + void (*dealloc)(detail::value_and_holder &) = nullptr; /// List of base classes of the newly created type list bases; @@ -204,17 +247,20 @@ struct type_record { /// Is the default (unique_ptr) holder type used? bool default_holder : 1; - PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) { - auto base_info = detail::get_type_info(*base, false); + /// Is the class definition local to the module shared object? + bool module_local : 1; + + PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) { + auto base_info = detail::get_type_info(base, false); if (!base_info) { - std::string tname(base->name()); + std::string tname(base.name()); detail::clean_type_id(tname); pybind11_fail("generic_type: type \"" + std::string(name) + "\" referenced unknown base type \"" + tname + "\""); } if (default_holder != base_info->default_holder) { - std::string tname(base->name()); + std::string tname(base.name()); detail::clean_type_id(tname); pybind11_fail("generic_type: type \"" + std::string(name) + "\" " + (default_holder ? "does not have" : "has") + @@ -228,7 +274,7 @@ struct type_record { dynamic_attr = true; if (caster) - base_info->implicit_casts.push_back(std::make_pair(type, caster)); + base_info->implicit_casts.emplace_back(type, caster); } }; @@ -238,6 +284,9 @@ inline function_call::function_call(function_record &f, handle p) : args_convert.reserve(f.nargs); } +/// Tag for a new-style `__init__` defined in `detail/init.h` +struct is_new_style_constructor { }; + /** * Partial template specializations to process custom attributes provided to * cpp_function_ and class_. These are either used to initialize the respective @@ -296,12 +345,16 @@ template <> struct process_attribute<is_operator> : process_attribute_default<is static void init(const is_operator &, function_record *r) { r->is_operator = true; } }; +template <> struct process_attribute<is_new_style_constructor> : process_attribute_default<is_new_style_constructor> { + static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; } +}; + /// Process a keyword argument attribute (*without* a default value) template <> struct process_attribute<arg> : process_attribute_default<arg> { static void init(const arg &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr, handle(), true /*convert*/); - r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert); + r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/); + r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none); } }; @@ -309,7 +362,7 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> { template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { static void init(const arg_v &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/); + r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/); if (!a.value) { #if !defined(NDEBUG) @@ -332,7 +385,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> { "Compile in debug mode for more information."); #endif } - r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert); + r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none); } }; @@ -345,7 +398,7 @@ struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attrib /// Process a parent class attribute (deprecated, does not support multiple inheritance) template <typename T> struct process_attribute<base<T>> : process_attribute_default<base<T>> { - static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); } + static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); } }; /// Process a multiple inheritance attribute @@ -369,12 +422,19 @@ struct process_attribute<metaclass> : process_attribute_default<metaclass> { static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; } }; +template <> +struct process_attribute<module_local> : process_attribute_default<module_local> { + static void init(const module_local &l, type_record *r) { r->module_local = l.value; } +}; /// Process an 'arithmetic' attribute for enums (does nothing here) template <> struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {}; -/*** +template <typename... Ts> +struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> { }; + +/** * Process a keep_alive call policy -- invokes keep_alive_impl during the * pre-call handler if both Nurse, Patient != 0 and use the post-call handler * otherwise @@ -410,6 +470,13 @@ template <typename... Args> struct process_attributes { } }; +template <typename T> +using is_call_guard = is_instantiation<call_guard, T>; + +/// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found) +template <typename... Extra> +using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type; + /// Check the number of named arguments at compile time template <typename... Extra, size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...), @@ -419,4 +486,4 @@ constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) { } NAMESPACE_END(detail) -NAMESPACE_END(pybind11) +NAMESPACE_END(PYBIND11_NAMESPACE) |