2016-01-17 21:36:44 +00:00
|
|
|
/*
|
2017-05-09 17:50:34 +00:00
|
|
|
pybind11/attr.h: Infrastructure for processing custom
|
2016-01-17 21:36:44 +00:00
|
|
|
type and function attributes
|
|
|
|
|
2016-04-17 18:21:41 +00:00
|
|
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
All rights reserved. Use of this source code is governed by a
|
|
|
|
BSD-style license that can be found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "cast.h"
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(pybind11)
|
|
|
|
|
2017-01-31 15:54:08 +00:00
|
|
|
/// \addtogroup annotations
|
|
|
|
/// @{
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Annotation for methods
|
|
|
|
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
|
|
|
|
|
2016-09-10 06:28:37 +00:00
|
|
|
/// Annotation for operators
|
|
|
|
struct is_operator { };
|
|
|
|
|
2016-02-04 22:02:07 +00:00
|
|
|
/// Annotation for parent scope
|
|
|
|
struct scope { handle value; scope(const handle &s) : value(s) { } };
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Annotation for documentation
|
|
|
|
struct doc { const char *value; doc(const char *value) : value(value) { } };
|
|
|
|
|
|
|
|
/// Annotation for function names
|
|
|
|
struct name { const char *value; name(const char *value) : value(value) { } };
|
|
|
|
|
|
|
|
/// Annotation indicating that a function is an overload associated with a given "sibling"
|
|
|
|
struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } };
|
|
|
|
|
|
|
|
/// Annotation indicating that a class derives from another given type
|
2016-09-12 03:03:20 +00:00
|
|
|
template <typename T> struct base {
|
|
|
|
PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
|
|
|
|
base() { }
|
|
|
|
};
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Keep patient alive while nurse lives
|
2017-01-22 14:23:53 +00:00
|
|
|
template <size_t Nurse, size_t Patient> struct keep_alive { };
|
2016-01-17 21:36:44 +00:00
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// Annotation indicating that a class is involved in a multiple inheritance relationship
|
|
|
|
struct multiple_inheritance { };
|
|
|
|
|
2016-10-10 23:12:48 +00:00
|
|
|
/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class
|
|
|
|
struct dynamic_attr { };
|
|
|
|
|
2016-12-16 14:00:46 +00:00
|
|
|
/// Annotation which enables the buffer protocol for a type
|
|
|
|
struct buffer_protocol { };
|
|
|
|
|
|
|
|
/// Annotation which requests that a special metaclass is created for a type
|
2017-02-16 22:02:56 +00:00
|
|
|
struct metaclass {
|
|
|
|
handle value;
|
|
|
|
|
|
|
|
PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.")
|
2017-04-29 19:31:06 +00:00
|
|
|
metaclass() {}
|
2017-02-16 22:02:56 +00:00
|
|
|
|
|
|
|
/// Override pybind11's default metaclass
|
|
|
|
explicit metaclass(handle value) : value(value) { }
|
|
|
|
};
|
2016-12-16 14:00:46 +00:00
|
|
|
|
2016-11-17 22:24:47 +00:00
|
|
|
/// Annotation to mark enums as an arithmetic type
|
|
|
|
struct arithmetic { };
|
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
/** \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{};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2017-01-31 15:54:08 +00:00
|
|
|
/// @} annotations
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
NAMESPACE_BEGIN(detail)
|
|
|
|
/* Forward declarations */
|
|
|
|
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;
|
2016-05-26 11:19:27 +00:00
|
|
|
template <typename... Args> struct init_alias;
|
2017-01-30 18:34:38 +00:00
|
|
|
inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret);
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Internal data structure which holds metadata about a keyword argument
|
|
|
|
struct argument_record {
|
|
|
|
const char *name; ///< Argument name
|
|
|
|
const char *descr; ///< Human-readable version of the argument value
|
|
|
|
handle value; ///< Associated Python object
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
bool convert : 1; ///< True if the argument is allowed to convert when loading
|
2016-01-17 21:36:44 +00:00
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
argument_record(const char *name, const char *descr, handle value, bool convert)
|
|
|
|
: name(name), descr(descr), value(value), convert(convert) { }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.)
|
|
|
|
struct function_record {
|
2016-09-10 06:28:37 +00:00
|
|
|
function_record()
|
|
|
|
: is_constructor(false), is_stateless(false), is_operator(false),
|
2016-11-20 04:41:32 +00:00
|
|
|
has_args(false), has_kwargs(false), is_method(false) { }
|
2016-09-10 06:28:37 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Function name
|
|
|
|
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
|
|
|
|
|
|
|
// User-specified documentation string
|
|
|
|
char *doc = nullptr;
|
|
|
|
|
|
|
|
/// Human-readable version of the function signature
|
|
|
|
char *signature = nullptr;
|
|
|
|
|
|
|
|
/// List of registered keyword arguments
|
|
|
|
std::vector<argument_record> args;
|
|
|
|
|
|
|
|
/// Pointer to lambda function which converts arguments and performs the actual call
|
2017-01-30 18:34:38 +00:00
|
|
|
handle (*impl) (function_call &) = nullptr;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Storage for the wrapped function pointer and captured data, if any
|
2016-05-10 14:05:03 +00:00
|
|
|
void *data[3] = { };
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Pointer to custom destructor for 'data' (if needed)
|
2016-05-10 14:05:03 +00:00
|
|
|
void (*free_data) (function_record *ptr) = nullptr;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Return value policy associated with this function
|
|
|
|
return_value_policy policy = return_value_policy::automatic;
|
|
|
|
|
|
|
|
/// True if name == '__init__'
|
2016-05-10 14:59:01 +00:00
|
|
|
bool is_constructor : 1;
|
|
|
|
|
2016-07-10 08:13:18 +00:00
|
|
|
/// True if this is a stateless function pointer
|
|
|
|
bool is_stateless : 1;
|
|
|
|
|
2016-09-10 06:28:37 +00:00
|
|
|
/// True if this is an operator (__add__), etc.
|
|
|
|
bool is_operator : 1;
|
|
|
|
|
2016-05-10 14:59:01 +00:00
|
|
|
/// True if the function has a '*args' argument
|
|
|
|
bool has_args : 1;
|
|
|
|
|
|
|
|
/// True if the function has a '**kwargs' argument
|
|
|
|
bool has_kwargs : 1;
|
|
|
|
|
2016-11-20 04:27:05 +00:00
|
|
|
/// True if this is a method
|
|
|
|
bool is_method : 1;
|
|
|
|
|
2017-01-22 04:42:14 +00:00
|
|
|
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
std::uint16_t nargs;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Python method object
|
|
|
|
PyMethodDef *def = nullptr;
|
|
|
|
|
2016-02-04 22:02:07 +00:00
|
|
|
/// Python handle to the parent scope (a class or a module)
|
|
|
|
handle scope;
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Python handle to the sibling function representing an overload chain
|
|
|
|
handle sibling;
|
|
|
|
|
|
|
|
/// Pointer to next overload
|
|
|
|
function_record *next = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Special data structure which (temporarily) holds metadata about a bound class
|
|
|
|
struct type_record {
|
2016-12-16 14:00:46 +00:00
|
|
|
PYBIND11_NOINLINE type_record()
|
2017-02-16 22:02:56 +00:00
|
|
|
: multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false) { }
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Handle to the parent scope
|
|
|
|
handle scope;
|
|
|
|
|
|
|
|
/// Name of the class
|
|
|
|
const char *name = nullptr;
|
|
|
|
|
|
|
|
// Pointer to RTTI type_info data structure
|
|
|
|
const std::type_info *type = nullptr;
|
|
|
|
|
|
|
|
/// How large is the underlying C++ type?
|
|
|
|
size_t type_size = 0;
|
|
|
|
|
|
|
|
/// How large is pybind11::instance<type>?
|
|
|
|
size_t instance_size = 0;
|
|
|
|
|
2017-03-21 00:15:20 +00:00
|
|
|
/// The global operator new can be overridden with a class-specific variant
|
|
|
|
void *(*operator_new)(size_t) = ::operator new;
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Function pointer to class_<..>::init_holder
|
|
|
|
void (*init_holder)(PyObject *, const void *) = nullptr;
|
|
|
|
|
|
|
|
/// Function pointer to class_<..>::dealloc
|
|
|
|
void (*dealloc)(PyObject *) = nullptr;
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// List of base classes of the newly created type
|
|
|
|
list bases;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// Optional docstring
|
|
|
|
const char *doc = nullptr;
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2017-02-16 22:02:56 +00:00
|
|
|
/// Custom metaclass (optional)
|
|
|
|
handle metaclass;
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// Multiple inheritance marker
|
2016-12-16 14:00:46 +00:00
|
|
|
bool multiple_inheritance : 1;
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2016-10-10 23:12:48 +00:00
|
|
|
/// Does the class manage a __dict__?
|
2016-12-16 14:00:46 +00:00
|
|
|
bool dynamic_attr : 1;
|
|
|
|
|
|
|
|
/// Does the class implement the buffer protocol?
|
|
|
|
bool buffer_protocol : 1;
|
|
|
|
|
2017-01-31 15:52:11 +00:00
|
|
|
/// Is the default (unique_ptr) holder type used?
|
|
|
|
bool default_holder : 1;
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
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());
|
|
|
|
detail::clean_type_id(tname);
|
|
|
|
pybind11_fail("generic_type: type \"" + std::string(name) +
|
|
|
|
"\" referenced unknown base type \"" + tname + "\"");
|
|
|
|
}
|
|
|
|
|
2017-01-31 15:52:11 +00:00
|
|
|
if (default_holder != base_info->default_holder) {
|
|
|
|
std::string tname(base->name());
|
|
|
|
detail::clean_type_id(tname);
|
|
|
|
pybind11_fail("generic_type: type \"" + std::string(name) + "\" " +
|
|
|
|
(default_holder ? "does not have" : "has") +
|
|
|
|
" a non-default holder type while its base \"" + tname + "\" " +
|
|
|
|
(base_info->default_holder ? "does not" : "does"));
|
|
|
|
}
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
bases.append((PyObject *) base_info->type);
|
|
|
|
|
2016-10-14 16:01:17 +00:00
|
|
|
if (base_info->type->tp_dictoffset != 0)
|
|
|
|
dynamic_attr = true;
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
if (caster)
|
2017-04-21 21:14:22 +00:00
|
|
|
base_info->implicit_casts.emplace_back(type, caster);
|
2016-09-11 11:00:40 +00:00
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
inline function_call::function_call(function_record &f, handle p) :
|
|
|
|
func(f), parent(p) {
|
|
|
|
args.reserve(f.nargs);
|
|
|
|
args_convert.reserve(f.nargs);
|
|
|
|
}
|
2017-01-30 18:34:38 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/**
|
|
|
|
* Partial template specializations to process custom attributes provided to
|
|
|
|
* cpp_function_ and class_. These are either used to initialize the respective
|
2016-09-11 11:00:40 +00:00
|
|
|
* fields in the type_record and function_record data structures or executed at
|
|
|
|
* runtime to deal with custom call policies (e.g. keep_alive).
|
2016-01-17 21:36:44 +00:00
|
|
|
*/
|
|
|
|
template <typename T, typename SFINAE = void> struct process_attribute;
|
|
|
|
|
|
|
|
template <typename T> struct process_attribute_default {
|
|
|
|
/// Default implementation: do nothing
|
|
|
|
static void init(const T &, function_record *) { }
|
|
|
|
static void init(const T &, type_record *) { }
|
2017-01-30 18:34:38 +00:00
|
|
|
static void precall(function_call &) { }
|
|
|
|
static void postcall(function_call &, handle) { }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Process an attribute specifying the function's name
|
|
|
|
template <> struct process_attribute<name> : process_attribute_default<name> {
|
|
|
|
static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process an attribute specifying the function's docstring
|
|
|
|
template <> struct process_attribute<doc> : process_attribute_default<doc> {
|
|
|
|
static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process an attribute specifying the function's docstring (provided as a C-style string)
|
|
|
|
template <> struct process_attribute<const char *> : process_attribute_default<const char *> {
|
|
|
|
static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); }
|
|
|
|
static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); }
|
|
|
|
};
|
|
|
|
template <> struct process_attribute<char *> : process_attribute<const char *> { };
|
|
|
|
|
|
|
|
/// Process an attribute indicating the function's return value policy
|
|
|
|
template <> struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> {
|
|
|
|
static void init(const return_value_policy &p, function_record *r) { r->policy = p; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process an attribute which indicates that this is an overloaded function associated with a given sibling
|
|
|
|
template <> struct process_attribute<sibling> : process_attribute_default<sibling> {
|
|
|
|
static void init(const sibling &s, function_record *r) { r->sibling = s.value; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process an attribute which indicates that this function is a method
|
|
|
|
template <> struct process_attribute<is_method> : process_attribute_default<is_method> {
|
2016-11-20 04:27:05 +00:00
|
|
|
static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
2016-02-04 22:02:07 +00:00
|
|
|
/// Process an attribute which indicates the parent scope of a method
|
|
|
|
template <> struct process_attribute<scope> : process_attribute_default<scope> {
|
|
|
|
static void init(const scope &s, function_record *r) { r->scope = s.value; }
|
|
|
|
};
|
|
|
|
|
2016-09-10 06:28:37 +00:00
|
|
|
/// Process an attribute which indicates that this function is an operator
|
|
|
|
template <> struct process_attribute<is_operator> : process_attribute_default<is_operator> {
|
|
|
|
static void init(const is_operator &, function_record *r) { r->is_operator = true; }
|
|
|
|
};
|
2016-02-04 22:02:07 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// 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) {
|
2016-11-20 04:27:05 +00:00
|
|
|
if (r->is_method && r->args.empty())
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
r->args.emplace_back("self", nullptr, handle(), true /*convert*/);
|
|
|
|
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process a keyword argument attribute (*with* a default value)
|
2016-09-05 22:49:21 +00:00
|
|
|
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
|
|
|
static void init(const arg_v &a, function_record *r) {
|
2016-11-20 04:27:05 +00:00
|
|
|
if (r->is_method && r->args.empty())
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/);
|
2016-01-17 21:36:44 +00:00
|
|
|
|
2016-09-05 22:49:21 +00:00
|
|
|
if (!a.value) {
|
2016-02-09 08:46:11 +00:00
|
|
|
#if !defined(NDEBUG)
|
2017-02-08 07:45:51 +00:00
|
|
|
std::string descr("'");
|
|
|
|
if (a.name) descr += std::string(a.name) + ": ";
|
|
|
|
descr += a.type + "'";
|
2016-11-20 04:27:05 +00:00
|
|
|
if (r->is_method) {
|
2016-04-01 10:17:03 +00:00
|
|
|
if (r->name)
|
2016-11-20 04:27:05 +00:00
|
|
|
descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'";
|
2016-04-01 10:17:03 +00:00
|
|
|
else
|
2016-11-20 04:27:05 +00:00
|
|
|
descr += " in method of '" + (std::string) str(r->scope) + "'";
|
2016-04-01 10:17:03 +00:00
|
|
|
} else if (r->name) {
|
2017-02-08 07:45:51 +00:00
|
|
|
descr += " in function '" + (std::string) r->name + "'";
|
2016-04-01 10:17:03 +00:00
|
|
|
}
|
2017-02-08 07:45:51 +00:00
|
|
|
pybind11_fail("arg(): could not convert default argument "
|
2016-04-01 10:17:03 +00:00
|
|
|
+ descr + " into a Python object (type not registered yet?)");
|
2016-02-09 08:46:11 +00:00
|
|
|
#else
|
2017-02-08 07:45:51 +00:00
|
|
|
pybind11_fail("arg(): could not convert default argument "
|
2016-02-09 08:46:11 +00:00
|
|
|
"into a Python object (type not registered yet?). "
|
|
|
|
"Compile in debug mode for more information.");
|
|
|
|
#endif
|
|
|
|
}
|
Add support for non-converting arguments
This adds support for controlling the `convert` flag of arguments
through the py::arg annotation. This then allows arguments to be
flagged as non-converting, which the type_caster is able to use to
request different behaviour.
Currently, AFAICS `convert` is only used for type converters of regular
pybind11-registered types; all of the other core type_casters ignore it.
We can, however, repurpose it to control internal conversion of
converters like Eigen and `array`: most usefully to give callers a way
to disable the conversion that would otherwise occur when a
`Eigen::Ref<const Eigen::Matrix>` argument is passed a numpy array that
requires conversion (either because it has an incompatible stride or the
wrong dtype).
Specifying a noconvert looks like one of these:
m.def("f1", &f, "a"_a.noconvert() = "default"); // Named, default, noconvert
m.def("f2", &f, "a"_a.noconvert()); // Named, no default, no converting
m.def("f3", &f, py::arg().noconvert()); // Unnamed, no default, no converting
(The last part--being able to declare a py::arg without a name--is new:
previous py::arg() only accepted named keyword arguments).
Such an non-convert argument is then passed `convert = false` by the
type caster when loading the argument. Whether this has an effect is up
to the type caster itself, but as mentioned above, this would be
extremely helpful for the Eigen support to give a nicer way to specify
a "no-copy" mode than the custom wrapper in the current PR, and
moreover isn't an Eigen-specific hack.
2017-01-23 08:50:00 +00:00
|
|
|
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-03-16 23:10:48 +00:00
|
|
|
/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees that)
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename T>
|
2016-09-08 14:36:01 +00:00
|
|
|
struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> {
|
2016-09-11 11:00:40 +00:00
|
|
|
static void init(const handle &h, type_record *r) { r->bases.append(h); }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// Process a parent class attribute (deprecated, does not support multiple inheritance)
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename T>
|
|
|
|
struct process_attribute<base<T>> : process_attribute_default<base<T>> {
|
2016-09-11 11:00:40 +00:00
|
|
|
static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Process a multiple inheritance attribute
|
|
|
|
template <>
|
|
|
|
struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> {
|
|
|
|
static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
2016-10-10 23:12:48 +00:00
|
|
|
template <>
|
|
|
|
struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr> {
|
|
|
|
static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; }
|
|
|
|
};
|
|
|
|
|
2016-12-16 14:00:46 +00:00
|
|
|
template <>
|
|
|
|
struct process_attribute<buffer_protocol> : process_attribute_default<buffer_protocol> {
|
|
|
|
static void init(const buffer_protocol &, type_record *r) { r->buffer_protocol = true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct process_attribute<metaclass> : process_attribute_default<metaclass> {
|
2017-02-16 22:02:56 +00:00
|
|
|
static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; }
|
2016-12-16 14:00:46 +00:00
|
|
|
};
|
|
|
|
|
2016-11-17 22:24:47 +00:00
|
|
|
|
|
|
|
/// Process an 'arithmetic' attribute for enums (does nothing here)
|
|
|
|
template <>
|
|
|
|
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
|
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
template <typename... Ts>
|
|
|
|
struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> { };
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/***
|
|
|
|
* 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
|
|
|
|
*/
|
2017-01-22 14:23:53 +00:00
|
|
|
template <size_t Nurse, size_t Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> {
|
|
|
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
2017-01-30 18:34:38 +00:00
|
|
|
static void precall(function_call &call) { keep_alive_impl(Nurse, Patient, call, handle()); }
|
2017-01-22 14:23:53 +00:00
|
|
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
2017-01-30 18:34:38 +00:00
|
|
|
static void postcall(function_call &, handle) { }
|
2017-01-22 14:23:53 +00:00
|
|
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
2017-01-30 18:34:38 +00:00
|
|
|
static void precall(function_call &) { }
|
2017-01-22 14:23:53 +00:00
|
|
|
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
2017-01-30 18:34:38 +00:00
|
|
|
static void postcall(function_call &call, handle ret) { keep_alive_impl(Nurse, Patient, call, ret); }
|
2016-01-17 21:36:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Recursively iterate over variadic template arguments
|
|
|
|
template <typename... Args> struct process_attributes {
|
|
|
|
static void init(const Args&... args, function_record *r) {
|
|
|
|
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... };
|
2016-01-21 16:18:47 +00:00
|
|
|
ignore_unused(unused);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
|
|
|
static void init(const Args&... args, type_record *r) {
|
|
|
|
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... };
|
2016-01-21 16:18:47 +00:00
|
|
|
ignore_unused(unused);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
2017-01-30 18:34:38 +00:00
|
|
|
static void precall(function_call &call) {
|
|
|
|
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(call), 0) ... };
|
2016-01-21 16:18:47 +00:00
|
|
|
ignore_unused(unused);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
2017-01-30 18:34:38 +00:00
|
|
|
static void postcall(function_call &call, handle fn_ret) {
|
|
|
|
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0) ... };
|
2016-01-21 16:18:47 +00:00
|
|
|
ignore_unused(unused);
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-03-16 10:22:26 +00:00
|
|
|
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>
|
2017-03-29 09:55:18 +00:00
|
|
|
using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extra...>::type;
|
2017-03-16 10:22:26 +00:00
|
|
|
|
2016-06-03 22:27:32 +00:00
|
|
|
/// Check the number of named arguments at compile time
|
|
|
|
template <typename... Extra,
|
|
|
|
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),
|
|
|
|
size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)>
|
2017-01-22 04:42:14 +00:00
|
|
|
constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
|
|
|
|
return named == 0 || (self + named + has_args + has_kwargs) == nargs;
|
2016-06-03 22:27:32 +00:00
|
|
|
}
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
NAMESPACE_END(detail)
|
|
|
|
NAMESPACE_END(pybind11)
|