2015-07-05 18:05:44 +00:00
|
|
|
/*
|
2016-01-17 21:36:44 +00:00
|
|
|
pybind11/pybind11.h: Main header file of the C++11 python
|
|
|
|
binding generator library
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-04-17 18:21:41 +00:00
|
|
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
2015-07-05 18:05: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.
|
|
|
|
*/
|
|
|
|
|
2015-07-11 15:41:48 +00:00
|
|
|
#pragma once
|
2015-07-05 18:05:44 +00:00
|
|
|
|
|
|
|
#if defined(_MSC_VER)
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma warning(push)
|
2016-08-24 23:43:33 +00:00
|
|
|
# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
2016-08-24 23:43:33 +00:00
|
|
|
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
|
|
|
|
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
|
2016-09-11 11:00:40 +00:00
|
|
|
# pragma warning(disable: 4702) // warning C4702: unreachable code
|
2016-09-22 22:27:59 +00:00
|
|
|
# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified
|
2016-08-24 23:43:33 +00:00
|
|
|
#elif defined(__INTEL_COMPILER)
|
2016-02-18 20:25:51 +00:00
|
|
|
# pragma warning(push)
|
2016-08-24 23:43:33 +00:00
|
|
|
# pragma warning(disable: 186) // pointless comparison of unsigned integer with zero
|
|
|
|
# pragma warning(disable: 1334) // the "template" keyword used for syntactic disambiguation may only be used within a template
|
|
|
|
# pragma warning(disable: 2196) // warning #2196: routine is both "inline" and "noinline"
|
2016-05-01 18:47:49 +00:00
|
|
|
#elif defined(__GNUG__) && !defined(__clang__)
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma GCC diagnostic push
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
|
|
|
|
# pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
|
|
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
2016-05-15 21:54:34 +00:00
|
|
|
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
|
|
|
# pragma GCC diagnostic ignored "-Wattributes"
|
2015-07-05 18:05:44 +00:00
|
|
|
#endif
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
#include "attr.h"
|
2016-11-15 11:38:05 +00:00
|
|
|
#include "options.h"
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2015-10-15 16:13:33 +00:00
|
|
|
NAMESPACE_BEGIN(pybind11)
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2015-07-26 14:33:49 +00:00
|
|
|
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
|
2015-07-11 15:41:48 +00:00
|
|
|
class cpp_function : public function {
|
2015-07-26 14:33:49 +00:00
|
|
|
public:
|
2015-07-11 15:41:48 +00:00
|
|
|
cpp_function() { }
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/// Construct a cpp_function from a vanilla function pointer
|
2016-01-17 21:36:36 +00:00
|
|
|
template <typename Return, typename... Args, typename... Extra>
|
2016-10-21 16:51:14 +00:00
|
|
|
cpp_function(Return (*f)(Args...), const Extra&... extra) {
|
2016-05-10 14:05:03 +00:00
|
|
|
initialize(f, f, extra...);
|
2015-07-26 14:33:49 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/// Construct a cpp_function from a lambda function (possibly with internal state)
|
2016-10-21 16:51:14 +00:00
|
|
|
template <typename Func, typename... Extra> cpp_function(Func &&f, const Extra&... extra) {
|
2015-07-29 15:43:52 +00:00
|
|
|
initialize(std::forward<Func>(f),
|
2015-07-26 14:33:49 +00:00
|
|
|
(typename detail::remove_class<decltype(
|
2016-01-17 21:36:44 +00:00
|
|
|
&std::remove_reference<Func>::type::operator())>::type *) nullptr, extra...);
|
2015-07-26 14:33:49 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/// Construct a cpp_function from a class method (non-const)
|
|
|
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
2016-10-21 16:51:14 +00:00
|
|
|
cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
|
2015-07-29 15:43:52 +00:00
|
|
|
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
2016-01-17 21:36:44 +00:00
|
|
|
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/// Construct a cpp_function from a class method (const)
|
|
|
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
2016-10-21 16:51:14 +00:00
|
|
|
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
|
2015-07-29 15:43:52 +00:00
|
|
|
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
2016-01-17 21:36:44 +00:00
|
|
|
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
2015-07-26 14:33:49 +00:00
|
|
|
}
|
|
|
|
|
2015-09-04 21:42:12 +00:00
|
|
|
/// Return the function name
|
2016-01-17 21:36:44 +00:00
|
|
|
object name() const { return attr("__name__"); }
|
2015-09-04 21:42:12 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
protected:
|
2016-09-10 06:28:37 +00:00
|
|
|
/// Space optimization: don't inline this frequently instantiated fragment
|
|
|
|
PYBIND11_NOINLINE detail::function_record *make_function_record() {
|
|
|
|
return new detail::function_record();
|
|
|
|
}
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/// Special internal constructor for functors, lambda functions, etc.
|
2016-01-17 21:36:36 +00:00
|
|
|
template <typename Func, typename Return, typename... Args, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
|
2016-06-03 22:27:32 +00:00
|
|
|
static_assert(detail::expected_num_args<Extra...>(sizeof...(Args)),
|
|
|
|
"The number of named arguments does not match the function signature");
|
|
|
|
|
2016-01-17 21:36:36 +00:00
|
|
|
struct capture { typename std::remove_reference<Func>::type f; };
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
|
2016-09-10 06:28:37 +00:00
|
|
|
auto rec = make_function_record();
|
2015-07-29 15:43:52 +00:00
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/* Store the capture object directly in the function record if there is enough space */
|
|
|
|
if (sizeof(capture) <= sizeof(rec->data)) {
|
2016-07-10 08:13:18 +00:00
|
|
|
/* Without these pragmas, GCC warns that there might not be
|
|
|
|
enough space to use the placement new operator. However, the
|
|
|
|
'if' statement above ensures that this is the case. */
|
2016-07-07 20:26:04 +00:00
|
|
|
#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
|
2016-07-07 20:11:42 +00:00
|
|
|
# pragma GCC diagnostic push
|
|
|
|
# pragma GCC diagnostic ignored "-Wplacement-new"
|
|
|
|
#endif
|
2016-05-10 14:05:03 +00:00
|
|
|
new ((capture *) &rec->data) capture { std::forward<Func>(f) };
|
2016-07-07 20:26:04 +00:00
|
|
|
#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
|
2016-07-07 20:11:42 +00:00
|
|
|
# pragma GCC diagnostic pop
|
|
|
|
#endif
|
2016-05-10 14:05:03 +00:00
|
|
|
if (!std::is_trivially_destructible<Func>::value)
|
|
|
|
rec->free_data = [](detail::function_record *r) { ((capture *) &r->data)->~capture(); };
|
|
|
|
} else {
|
|
|
|
rec->data[0] = new capture { std::forward<Func>(f) };
|
|
|
|
rec->free_data = [](detail::function_record *r) { delete ((capture *) r->data[0]); };
|
|
|
|
}
|
2015-10-13 15:37:25 +00:00
|
|
|
|
2016-05-10 14:05:03 +00:00
|
|
|
/* Type casters for the function arguments and return value */
|
|
|
|
typedef detail::type_caster<typename std::tuple<Args...>> cast_in;
|
|
|
|
typedef detail::type_caster<typename std::conditional<
|
|
|
|
std::is_void<Return>::value, detail::void_type,
|
|
|
|
typename detail::intrinsic_type<Return>::type>::type> cast_out;
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Dispatch code which converts function arguments and performs the actual function call */
|
2016-05-10 14:59:01 +00:00
|
|
|
rec->impl = [](detail::function_record *rec, handle args, handle kwargs, handle parent) -> handle {
|
2016-05-10 14:05:03 +00:00
|
|
|
cast_in args_converter;
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Try to cast the function arguments into the C++ domain */
|
2016-05-10 14:59:01 +00:00
|
|
|
if (!args_converter.load_args(args, kwargs, true))
|
2016-01-17 21:36:41 +00:00
|
|
|
return PYBIND11_TRY_NEXT_OVERLOAD;
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/* Invoke call policy pre-call hook */
|
2016-05-10 14:05:03 +00:00
|
|
|
detail::process_attributes<Extra...>::precall(args);
|
|
|
|
|
|
|
|
/* Get a pointer to the capture object */
|
|
|
|
capture *cap = (capture *) (sizeof(capture) <= sizeof(rec->data)
|
|
|
|
? &rec->data : rec->data[0]);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-07-10 08:13:18 +00:00
|
|
|
/* Perform the function call */
|
2016-05-10 14:05:03 +00:00
|
|
|
handle result = cast_out::cast(args_converter.template call<Return>(cap->f),
|
|
|
|
rec->policy, parent);
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/* Invoke call policy post-call hook */
|
2016-05-10 14:05:03 +00:00
|
|
|
detail::process_attributes<Extra...>::postcall(args, result);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-01-17 21:36:39 +00:00
|
|
|
return result;
|
2015-07-26 14:33:49 +00:00
|
|
|
};
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/* Process any user-provided function attributes */
|
|
|
|
detail::process_attributes<Extra...>::init(extra..., rec);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Generate a readable signature describing the function's arguments and return value types */
|
2016-08-03 23:40:40 +00:00
|
|
|
using detail::descr; using detail::_;
|
|
|
|
PYBIND11_DESCR signature = _("(") + cast_in::element_names() + _(") -> ") + cast_out::name();
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Register the function with Python from generic (non-templated) code */
|
2016-05-10 14:05:03 +00:00
|
|
|
initialize_generic(rec, signature.text(), signature.types(), sizeof...(Args));
|
2016-05-10 14:59:01 +00:00
|
|
|
|
|
|
|
if (cast_in::has_args) rec->has_args = true;
|
|
|
|
if (cast_in::has_kwargs) rec->has_kwargs = true;
|
2016-07-10 08:13:18 +00:00
|
|
|
|
|
|
|
/* Stash some additional information used by an important optimization in 'functional.h' */
|
|
|
|
using FunctionType = Return (*)(Args...);
|
|
|
|
constexpr bool is_function_ptr =
|
|
|
|
std::is_convertible<Func, FunctionType>::value &&
|
|
|
|
sizeof(capture) == sizeof(void *);
|
|
|
|
if (is_function_ptr) {
|
|
|
|
rec->is_stateless = true;
|
|
|
|
rec->data[1] = (void *) &typeid(FunctionType);
|
|
|
|
}
|
2015-07-30 13:29:00 +00:00
|
|
|
}
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/// Register a function call with Python (generic non-templated code goes here)
|
2016-05-10 14:05:03 +00:00
|
|
|
void initialize_generic(detail::function_record *rec, const char *text,
|
2016-07-31 18:03:18 +00:00
|
|
|
const std::type_info *const *types, size_t args) {
|
2016-01-17 21:36:44 +00:00
|
|
|
|
2016-01-17 21:36:36 +00:00
|
|
|
/* Create copies of all referenced C-style strings */
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->name = strdup(rec->name ? rec->name : "");
|
|
|
|
if (rec->doc) rec->doc = strdup(rec->doc);
|
|
|
|
for (auto &a: rec->args) {
|
2016-01-17 21:36:36 +00:00
|
|
|
if (a.name)
|
|
|
|
a.name = strdup(a.name);
|
|
|
|
if (a.descr)
|
|
|
|
a.descr = strdup(a.descr);
|
|
|
|
else if (a.value)
|
2016-09-08 15:02:04 +00:00
|
|
|
a.descr = strdup(a.value.attr("__repr__")().cast<std::string>().c_str());
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
2016-07-10 08:13:18 +00:00
|
|
|
|
2016-01-17 21:36:36 +00:00
|
|
|
/* Generate a proper function signature */
|
|
|
|
std::string signature;
|
|
|
|
size_t type_depth = 0, char_index = 0, type_index = 0, arg_index = 0;
|
|
|
|
while (true) {
|
|
|
|
char c = text[char_index++];
|
|
|
|
if (c == '\0')
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (c == '{') {
|
2016-07-31 18:03:18 +00:00
|
|
|
// Write arg name for everything except *args, **kwargs and return type.
|
2016-08-03 23:40:40 +00:00
|
|
|
if (type_depth == 0 && text[char_index] != '*' && arg_index < args) {
|
2016-07-31 18:03:18 +00:00
|
|
|
if (!rec->args.empty()) {
|
|
|
|
signature += rec->args[arg_index].name;
|
|
|
|
} else if (arg_index == 0 && rec->class_) {
|
|
|
|
signature += "self";
|
|
|
|
} else {
|
|
|
|
signature += "arg" + std::to_string(arg_index - (rec->class_ ? 1 : 0));
|
|
|
|
}
|
|
|
|
signature += ": ";
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
|
|
|
++type_depth;
|
|
|
|
} else if (c == '}') {
|
|
|
|
--type_depth;
|
2016-08-03 23:40:40 +00:00
|
|
|
if (type_depth == 0) {
|
2016-07-31 18:03:18 +00:00
|
|
|
if (arg_index < rec->args.size() && rec->args[arg_index].descr) {
|
|
|
|
signature += "=";
|
2016-01-17 21:36:44 +00:00
|
|
|
signature += rec->args[arg_index].descr;
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
|
|
|
arg_index++;
|
|
|
|
}
|
|
|
|
} else if (c == '%') {
|
|
|
|
const std::type_info *t = types[type_index++];
|
2016-01-17 21:36:40 +00:00
|
|
|
if (!t)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("Internal error while parsing type signature (1)");
|
2016-10-23 14:43:03 +00:00
|
|
|
if (auto tinfo = detail::get_type_info(*t)) {
|
|
|
|
signature += tinfo->type->tp_name;
|
2016-01-17 21:36:36 +00:00
|
|
|
} else {
|
|
|
|
std::string tname(t->name());
|
|
|
|
detail::clean_type_id(tname);
|
|
|
|
signature += tname;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
signature += c;
|
|
|
|
}
|
|
|
|
}
|
2016-01-17 21:36:40 +00:00
|
|
|
if (type_depth != 0 || types[type_index] != nullptr)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("Internal error while parsing type signature (2)");
|
2016-01-17 21:36:36 +00:00
|
|
|
|
|
|
|
#if !defined(PYBIND11_CPP14)
|
|
|
|
delete[] types;
|
|
|
|
delete[] text;
|
|
|
|
#endif
|
2015-08-24 13:31:24 +00:00
|
|
|
|
2015-09-04 21:42:12 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
2016-01-17 21:36:44 +00:00
|
|
|
if (strcmp(rec->name, "__next__") == 0) {
|
|
|
|
std::free(rec->name);
|
|
|
|
rec->name = strdup("next");
|
2016-05-16 16:52:46 +00:00
|
|
|
} else if (strcmp(rec->name, "__bool__") == 0) {
|
|
|
|
std::free(rec->name);
|
|
|
|
rec->name = strdup("__nonzero__");
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
2015-09-04 21:42:12 +00:00
|
|
|
#endif
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->signature = strdup(signature.c_str());
|
|
|
|
rec->args.shrink_to_fit();
|
2016-05-15 21:54:13 +00:00
|
|
|
rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__");
|
2016-05-15 21:55:06 +00:00
|
|
|
rec->nargs = (uint16_t) args;
|
2015-09-04 21:42:12 +00:00
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
2016-01-17 21:36:44 +00:00
|
|
|
if (rec->sibling && PyMethod_Check(rec->sibling.ptr()))
|
|
|
|
rec->sibling = PyMethod_GET_FUNCTION(rec->sibling.ptr());
|
2015-09-04 21:42:12 +00:00
|
|
|
#endif
|
2015-07-29 15:43:52 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
detail::function_record *chain = nullptr, *chain_start = rec;
|
2016-10-25 01:58:22 +00:00
|
|
|
if (rec->sibling) {
|
|
|
|
if (PyCFunction_Check(rec->sibling.ptr())) {
|
2016-10-28 01:08:15 +00:00
|
|
|
auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GetSelf(rec->sibling.ptr()));
|
2016-10-25 01:58:22 +00:00
|
|
|
chain = (detail::function_record *) rec_capsule;
|
|
|
|
/* Never append a method to an overload chain of a parent class;
|
|
|
|
instead, hide the parent's overloads in this case */
|
2016-11-20 04:26:02 +00:00
|
|
|
if (chain->scope != rec->scope)
|
2016-10-25 01:58:22 +00:00
|
|
|
chain = nullptr;
|
|
|
|
}
|
|
|
|
// Don't trigger for things like the default __init__, which are wrapper_descriptors that we are intentionally replacing
|
|
|
|
else if (!rec->sibling.is_none() && rec->name[0] != '_')
|
|
|
|
pybind11_fail("Cannot overload existing non-function object \"" + std::string(rec->name) +
|
|
|
|
"\" with a function of the same name");
|
2015-10-01 14:46:03 +00:00
|
|
|
}
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
if (!chain) {
|
2016-01-17 21:36:41 +00:00
|
|
|
/* No existing overload was found, create a new function object */
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->def = new PyMethodDef();
|
|
|
|
memset(rec->def, 0, sizeof(PyMethodDef));
|
|
|
|
rec->def->ml_name = rec->name;
|
|
|
|
rec->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
|
|
|
|
rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
2016-02-04 22:02:07 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
capsule rec_capsule(rec, [](PyObject *o) {
|
|
|
|
destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr));
|
2016-01-17 21:36:41 +00:00
|
|
|
});
|
2016-02-04 22:02:07 +00:00
|
|
|
|
|
|
|
object scope_module;
|
|
|
|
if (rec->scope) {
|
2016-09-20 23:06:32 +00:00
|
|
|
if (hasattr(rec->scope, "__module__")) {
|
|
|
|
scope_module = rec->scope.attr("__module__");
|
|
|
|
} else if (hasattr(rec->scope, "__name__")) {
|
|
|
|
scope_module = rec->scope.attr("__name__");
|
|
|
|
}
|
2016-02-04 22:02:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr());
|
2015-07-05 18:05:44 +00:00
|
|
|
if (!m_ptr)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("cpp_function::cpp_function(): Could not allocate function object");
|
2015-07-05 18:05:44 +00:00
|
|
|
} else {
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Append at the end of the overload chain */
|
2016-01-17 21:36:44 +00:00
|
|
|
m_ptr = rec->sibling.ptr();
|
2015-07-05 18:05:44 +00:00
|
|
|
inc_ref();
|
2016-01-17 21:36:44 +00:00
|
|
|
chain_start = chain;
|
|
|
|
while (chain->next)
|
|
|
|
chain = chain->next;
|
|
|
|
chain->next = rec;
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2015-07-30 13:29:00 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
std::string signatures;
|
2015-07-29 15:43:52 +00:00
|
|
|
int index = 0;
|
2016-01-17 21:36:44 +00:00
|
|
|
/* Create a nice pydoc rec including all signatures and
|
2016-01-17 21:36:41 +00:00
|
|
|
docstrings of the functions in the overload chain */
|
2016-11-15 11:38:05 +00:00
|
|
|
if (chain && options::show_function_signatures()) {
|
2016-03-08 21:42:12 +00:00
|
|
|
// First a generic signature
|
|
|
|
signatures += rec->name;
|
|
|
|
signatures += "(*args, **kwargs)\n";
|
|
|
|
signatures += "Overloaded function.\n\n";
|
|
|
|
}
|
|
|
|
// Then specific overload signatures
|
2016-01-17 21:36:44 +00:00
|
|
|
for (auto it = chain_start; it != nullptr; it = it->next) {
|
2016-11-15 11:38:05 +00:00
|
|
|
if (options::show_function_signatures()) {
|
|
|
|
if (chain)
|
|
|
|
signatures += std::to_string(++index) + ". ";
|
|
|
|
signatures += rec->name;
|
|
|
|
signatures += it->signature;
|
2016-01-17 21:36:36 +00:00
|
|
|
signatures += "\n";
|
2016-11-15 11:38:05 +00:00
|
|
|
}
|
|
|
|
if (it->doc && strlen(it->doc) > 0 && options::show_user_defined_docstrings()) {
|
|
|
|
if (options::show_function_signatures()) signatures += "\n";
|
2016-02-28 22:52:37 +00:00
|
|
|
signatures += it->doc;
|
2016-11-15 11:38:05 +00:00
|
|
|
if (options::show_function_signatures()) signatures += "\n";
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
2015-07-29 15:43:52 +00:00
|
|
|
if (it->next)
|
2015-07-05 18:05:44 +00:00
|
|
|
signatures += "\n";
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/* Install docstring */
|
2015-07-05 18:05:44 +00:00
|
|
|
PyCFunctionObject *func = (PyCFunctionObject *) m_ptr;
|
|
|
|
if (func->m_ml->ml_doc)
|
2016-01-17 21:36:41 +00:00
|
|
|
std::free((char *) func->m_ml->ml_doc);
|
2015-07-05 18:05:44 +00:00
|
|
|
func->m_ml->ml_doc = strdup(signatures.c_str());
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
if (rec->class_) {
|
|
|
|
m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->class_.ptr());
|
2015-07-05 18:05:44 +00:00
|
|
|
if (!m_ptr)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("cpp_function::cpp_function(): Could not allocate instance method object");
|
2015-07-05 18:05:44 +00:00
|
|
|
Py_DECREF(func);
|
|
|
|
}
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/// When a cpp_function is GCed, release any memory allocated by pybind11
|
|
|
|
static void destruct(detail::function_record *rec) {
|
|
|
|
while (rec) {
|
|
|
|
detail::function_record *next = rec->next;
|
|
|
|
if (rec->free_data)
|
2016-05-10 14:05:03 +00:00
|
|
|
rec->free_data(rec);
|
2016-01-17 21:36:44 +00:00
|
|
|
std::free((char *) rec->name);
|
|
|
|
std::free((char *) rec->doc);
|
|
|
|
std::free((char *) rec->signature);
|
|
|
|
for (auto &arg: rec->args) {
|
|
|
|
std::free((char *) arg.name);
|
|
|
|
std::free((char *) arg.descr);
|
|
|
|
arg.value.dec_ref();
|
|
|
|
}
|
|
|
|
if (rec->def) {
|
|
|
|
std::free((char *) rec->def->ml_doc);
|
|
|
|
delete rec->def;
|
|
|
|
}
|
|
|
|
delete rec;
|
|
|
|
rec = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Main dispatch logic for calls to functions bound using pybind11
|
|
|
|
static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject *kwargs) {
|
|
|
|
/* Iterator over the list of potentially admissible overloads */
|
|
|
|
detail::function_record *overloads = (detail::function_record *) PyCapsule_GetPointer(self, nullptr),
|
|
|
|
*it = overloads;
|
|
|
|
|
|
|
|
/* Need to know how many arguments + keyword arguments there are to pick the right overload */
|
2016-05-29 11:40:40 +00:00
|
|
|
size_t nargs = (size_t) PyTuple_GET_SIZE(args),
|
|
|
|
nkwargs = kwargs ? (size_t) PyDict_Size(kwargs) : 0;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
2016-05-10 14:59:01 +00:00
|
|
|
handle parent = nargs > 0 ? PyTuple_GET_ITEM(args, 0) : nullptr,
|
2016-01-17 21:36:44 +00:00
|
|
|
result = PYBIND11_TRY_NEXT_OVERLOAD;
|
|
|
|
try {
|
|
|
|
for (; it != nullptr; it = it->next) {
|
2016-10-28 01:08:15 +00:00
|
|
|
auto args_ = reinterpret_borrow<tuple>(args);
|
2016-05-10 14:59:01 +00:00
|
|
|
size_t kwargs_consumed = 0;
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
/* For each overload:
|
|
|
|
1. If the required list of arguments is longer than the
|
|
|
|
actually provided amount, create a copy of the argument
|
|
|
|
list and fill in any available keyword/default arguments.
|
|
|
|
2. Ensure that all keyword arguments were "consumed"
|
|
|
|
3. Call the function call dispatcher (function_record::impl)
|
|
|
|
*/
|
2016-05-10 14:59:01 +00:00
|
|
|
size_t nargs_ = nargs;
|
|
|
|
if (nargs < it->args.size()) {
|
|
|
|
nargs_ = it->args.size();
|
|
|
|
args_ = tuple(nargs_);
|
|
|
|
for (size_t i = 0; i < nargs; ++i) {
|
2016-01-17 21:36:44 +00:00
|
|
|
handle item = PyTuple_GET_ITEM(args, i);
|
|
|
|
PyTuple_SET_ITEM(args_.ptr(), i, item.inc_ref().ptr());
|
|
|
|
}
|
|
|
|
|
|
|
|
int arg_ctr = 0;
|
|
|
|
for (auto const &it2 : it->args) {
|
|
|
|
int index = arg_ctr++;
|
|
|
|
if (PyTuple_GET_ITEM(args_.ptr(), index))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
handle value;
|
|
|
|
if (kwargs)
|
|
|
|
value = PyDict_GetItemString(kwargs, it2.name);
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
kwargs_consumed++;
|
|
|
|
else if (it2.value)
|
|
|
|
value = it2.value;
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
PyTuple_SET_ITEM(args_.ptr(), index, value.inc_ref().ptr());
|
|
|
|
} else {
|
2016-05-10 14:59:01 +00:00
|
|
|
kwargs_consumed = (size_t) -1; /* definite failure */
|
2016-01-17 21:36:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-01 12:42:20 +00:00
|
|
|
|
|
|
|
try {
|
2016-05-10 14:59:01 +00:00
|
|
|
if ((kwargs_consumed == nkwargs || it->has_kwargs) &&
|
|
|
|
(nargs_ == it->nargs || it->has_args))
|
|
|
|
result = it->impl(it, args_, kwargs, parent);
|
2016-07-01 14:07:35 +00:00
|
|
|
} catch (reference_cast_error &) {
|
2016-05-01 12:42:20 +00:00
|
|
|
result = PYBIND11_TRY_NEXT_OVERLOAD;
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
|
|
|
|
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD)
|
|
|
|
break;
|
|
|
|
}
|
2016-09-10 09:58:02 +00:00
|
|
|
} catch (error_already_set &e) {
|
|
|
|
e.restore();
|
2016-06-17 21:35:59 +00:00
|
|
|
return nullptr;
|
2016-01-17 21:36:44 +00:00
|
|
|
} catch (...) {
|
2016-06-17 21:35:59 +00:00
|
|
|
/* When an exception is caught, give each registered exception
|
|
|
|
translator a chance to translate it to a Python exception
|
|
|
|
in reverse order of registration.
|
2016-07-18 08:47:10 +00:00
|
|
|
|
2016-06-17 21:35:59 +00:00
|
|
|
A translator may choose to do one of the following:
|
2016-07-18 08:47:10 +00:00
|
|
|
|
2016-06-17 21:35:59 +00:00
|
|
|
- catch the exception and call PyErr_SetString or PyErr_SetObject
|
|
|
|
to set a standard (or custom) Python exception, or
|
|
|
|
- do nothing and let the exception fall through to the next translator, or
|
|
|
|
- delegate translation to the next translator by throwing a new type of exception. */
|
|
|
|
|
2016-07-18 08:47:10 +00:00
|
|
|
auto last_exception = std::current_exception();
|
2016-06-17 21:35:59 +00:00
|
|
|
auto ®istered_exception_translators = pybind11::detail::get_internals().registered_exception_translators;
|
|
|
|
for (auto& translator : registered_exception_translators) {
|
|
|
|
try {
|
|
|
|
translator(last_exception);
|
|
|
|
} catch (...) {
|
|
|
|
last_exception = std::current_exception();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
PyErr_SetString(PyExc_SystemError, "Exception escaped from default exception translator!");
|
2016-01-17 21:36:44 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) {
|
2016-09-10 06:28:37 +00:00
|
|
|
if (overloads->is_operator)
|
|
|
|
return handle(Py_NotImplemented).inc_ref().ptr();
|
|
|
|
|
2016-09-12 02:44:37 +00:00
|
|
|
std::string msg = std::string(overloads->name) + "(): incompatible " +
|
|
|
|
std::string(overloads->is_constructor ? "constructor" : "function") +
|
|
|
|
" arguments. The following argument types are supported:\n";
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
int ctr = 0;
|
|
|
|
for (detail::function_record *it2 = overloads; it2 != nullptr; it2 = it2->next) {
|
|
|
|
msg += " "+ std::to_string(++ctr) + ". ";
|
2016-07-17 21:43:00 +00:00
|
|
|
|
|
|
|
bool wrote_sig = false;
|
|
|
|
if (overloads->is_constructor) {
|
2016-07-31 18:03:18 +00:00
|
|
|
// For a constructor, rewrite `(self: Object, arg0, ...) -> NoneType` as `Object(arg0, ...)`
|
2016-07-17 21:43:00 +00:00
|
|
|
std::string sig = it2->signature;
|
2016-07-31 18:03:18 +00:00
|
|
|
size_t start = sig.find('(') + 7; // skip "(self: "
|
2016-07-17 21:43:00 +00:00
|
|
|
if (start < sig.size()) {
|
|
|
|
// End at the , for the next argument
|
|
|
|
size_t end = sig.find(", "), next = end + 2;
|
|
|
|
size_t ret = sig.rfind(" -> ");
|
|
|
|
// Or the ), if there is no comma:
|
|
|
|
if (end >= sig.size()) next = end = sig.find(')');
|
|
|
|
if (start < end && next < sig.size()) {
|
|
|
|
msg.append(sig, start, end - start);
|
|
|
|
msg += '(';
|
|
|
|
msg.append(sig, next, ret - next);
|
|
|
|
wrote_sig = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!wrote_sig) msg += it2->signature;
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
msg += "\n";
|
|
|
|
}
|
2016-09-12 02:44:37 +00:00
|
|
|
msg += "\nInvoked with: ";
|
2016-10-28 01:08:15 +00:00
|
|
|
auto args_ = reinterpret_borrow<tuple>(args);
|
2016-07-18 08:47:10 +00:00
|
|
|
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
|
2016-10-25 20:12:39 +00:00
|
|
|
msg += static_cast<std::string>(pybind11::str(args_[ti]));
|
2016-05-24 07:19:35 +00:00
|
|
|
if ((ti + 1) != args_.size() )
|
|
|
|
msg += ", ";
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
|
|
|
return nullptr;
|
|
|
|
} else if (!result) {
|
|
|
|
std::string msg = "Unable to convert function return value to a "
|
|
|
|
"Python type! The signature was\n\t";
|
|
|
|
msg += it->signature;
|
|
|
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
|
|
|
return nullptr;
|
|
|
|
} else {
|
|
|
|
if (overloads->is_constructor) {
|
2016-04-30 17:56:10 +00:00
|
|
|
/* When a constructor ran successfully, the corresponding
|
2016-01-17 21:36:44 +00:00
|
|
|
holder type (e.g. std::unique_ptr) must still be initialized. */
|
2016-05-10 14:59:01 +00:00
|
|
|
PyObject *inst = PyTuple_GET_ITEM(args, 0);
|
2016-01-17 21:36:44 +00:00
|
|
|
auto tinfo = detail::get_type_info(Py_TYPE(inst));
|
|
|
|
tinfo->init_holder(inst, nullptr);
|
|
|
|
}
|
|
|
|
return result.ptr();
|
|
|
|
}
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/// Wrapper for Python extension modules
|
2015-07-05 18:05:44 +00:00
|
|
|
class module : public object {
|
|
|
|
public:
|
2015-10-18 14:48:30 +00:00
|
|
|
PYBIND11_OBJECT_DEFAULT(module, object, PyModule_Check)
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-10-16 20:27:42 +00:00
|
|
|
explicit module(const char *name, const char *doc = nullptr) {
|
2016-11-15 11:38:05 +00:00
|
|
|
if (!options::show_user_defined_docstrings()) doc = nullptr;
|
2015-09-04 21:42:12 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
2015-07-05 18:05:44 +00:00
|
|
|
PyModuleDef *def = new PyModuleDef();
|
|
|
|
memset(def, 0, sizeof(PyModuleDef));
|
|
|
|
def->m_name = name;
|
|
|
|
def->m_doc = doc;
|
|
|
|
def->m_size = -1;
|
|
|
|
Py_INCREF(def);
|
|
|
|
m_ptr = PyModule_Create(def);
|
2015-09-04 21:42:12 +00:00
|
|
|
#else
|
|
|
|
m_ptr = Py_InitModule3(name, nullptr, doc);
|
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
if (m_ptr == nullptr)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("Internal error in module::module()");
|
2015-07-05 18:05:44 +00:00
|
|
|
inc_ref();
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Func, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
module &def(const char *name_, Func &&f, const Extra& ... extra) {
|
2016-09-20 23:06:32 +00:00
|
|
|
cpp_function func(std::forward<Func>(f), name(name_), scope(*this),
|
|
|
|
sibling(getattr(*this, name_, none())), extra...);
|
2016-10-25 01:58:22 +00:00
|
|
|
// NB: allow overwriting here because cpp_function sets up a chain with the intention of
|
|
|
|
// overwriting (and has already checked internally that it isn't overwriting non-functions).
|
|
|
|
add_object(name_, func, true /* overwrite */);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-11 15:41:48 +00:00
|
|
|
module def_submodule(const char *name, const char *doc = nullptr) {
|
2015-07-05 18:05:44 +00:00
|
|
|
std::string full_name = std::string(PyModule_GetName(m_ptr))
|
|
|
|
+ std::string(".") + std::string(name);
|
2016-10-28 01:08:15 +00:00
|
|
|
auto result = reinterpret_borrow<module>(PyImport_AddModule(full_name.c_str()));
|
2016-11-15 11:38:05 +00:00
|
|
|
if (doc && options::show_user_defined_docstrings())
|
2015-10-15 16:13:33 +00:00
|
|
|
result.attr("__doc__") = pybind11::str(doc);
|
2015-07-05 18:05:44 +00:00
|
|
|
attr(name) = result;
|
|
|
|
return result;
|
|
|
|
}
|
2015-10-13 21:44:25 +00:00
|
|
|
|
|
|
|
static module import(const char *name) {
|
2015-12-26 13:04:52 +00:00
|
|
|
PyObject *obj = PyImport_ImportModule(name);
|
|
|
|
if (!obj)
|
2016-10-13 08:34:52 +00:00
|
|
|
throw import_error("Module \"" + std::string(name) + "\" not found!");
|
2016-10-28 01:08:15 +00:00
|
|
|
return reinterpret_steal<module>(obj);
|
2015-10-13 21:44:25 +00:00
|
|
|
}
|
2016-10-25 01:58:22 +00:00
|
|
|
|
|
|
|
// Adds an object to the module using the given name. Throws if an object with the given name
|
|
|
|
// already exists.
|
|
|
|
//
|
|
|
|
// overwrite should almost always be false: attempting to overwrite objects that pybind11 has
|
|
|
|
// established will, in most cases, break things.
|
|
|
|
PYBIND11_NOINLINE void add_object(const char *name, object &obj, bool overwrite = false) {
|
|
|
|
if (!overwrite && hasattr(*this, name))
|
|
|
|
pybind11_fail("Error during initialization: multiple incompatible definitions with name \"" +
|
|
|
|
std::string(name) + "\"");
|
|
|
|
|
|
|
|
obj.inc_ref(); // PyModule_AddObject() steals a reference
|
|
|
|
PyModule_AddObject(ptr(), name, obj.ptr());
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(detail)
|
2016-10-10 23:12:48 +00:00
|
|
|
extern "C" inline PyObject *get_dict(PyObject *op, void *) {
|
2016-10-12 21:20:32 +00:00
|
|
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
|
|
|
if (!dict) {
|
|
|
|
dict = PyDict_New();
|
2016-10-10 23:12:48 +00:00
|
|
|
}
|
2016-10-12 21:20:32 +00:00
|
|
|
Py_XINCREF(dict);
|
|
|
|
return dict;
|
2016-10-10 23:12:48 +00:00
|
|
|
}
|
|
|
|
|
2016-10-12 21:20:32 +00:00
|
|
|
extern "C" inline int set_dict(PyObject *op, PyObject *new_dict, void *) {
|
|
|
|
if (!PyDict_Check(new_dict)) {
|
2016-10-10 23:12:48 +00:00
|
|
|
PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'",
|
2016-10-12 21:20:32 +00:00
|
|
|
Py_TYPE(new_dict)->tp_name);
|
2016-10-10 23:12:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2016-10-12 21:20:32 +00:00
|
|
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
|
|
|
Py_INCREF(new_dict);
|
|
|
|
Py_CLEAR(dict);
|
|
|
|
dict = new_dict;
|
2016-10-10 23:12:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyGetSetDef generic_getset[] = {
|
|
|
|
{const_cast<char*>("__dict__"), get_dict, set_dict, nullptr, nullptr},
|
|
|
|
{nullptr, nullptr, nullptr, nullptr, nullptr}
|
|
|
|
};
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/// Generic support for creating new Python heap types
|
2016-01-17 21:36:41 +00:00
|
|
|
class generic_type : public object {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename...> friend class class_;
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
2016-01-17 21:36:41 +00:00
|
|
|
PYBIND11_OBJECT_DEFAULT(generic_type, object, PyType_Check)
|
2016-01-17 21:36:44 +00:00
|
|
|
protected:
|
|
|
|
void initialize(type_record *rec) {
|
2016-05-31 07:53:28 +00:00
|
|
|
auto &internals = get_internals();
|
|
|
|
auto tindex = std::type_index(*(rec->type));
|
|
|
|
|
2016-10-23 14:43:03 +00:00
|
|
|
if (get_type_info(*(rec->type)))
|
2016-05-31 07:53:28 +00:00
|
|
|
pybind11_fail("generic_type: type \"" + std::string(rec->name) +
|
|
|
|
"\" is already registered!");
|
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec->name));
|
2016-07-11 21:40:28 +00:00
|
|
|
object scope_module;
|
|
|
|
if (rec->scope) {
|
2016-10-25 01:58:22 +00:00
|
|
|
if (hasattr(rec->scope, rec->name))
|
|
|
|
pybind11_fail("generic_type: cannot initialize type \"" + std::string(rec->name) +
|
|
|
|
"\": an object with that name is already defined");
|
|
|
|
|
2016-09-20 23:06:32 +00:00
|
|
|
if (hasattr(rec->scope, "__module__")) {
|
|
|
|
scope_module = rec->scope.attr("__module__");
|
|
|
|
} else if (hasattr(rec->scope, "__name__")) {
|
|
|
|
scope_module = rec->scope.attr("__name__");
|
|
|
|
}
|
2016-07-11 21:40:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
|
|
|
/* Qualified names for Python >= 3.3 */
|
|
|
|
object scope_qualname;
|
2016-09-20 23:06:32 +00:00
|
|
|
if (rec->scope && hasattr(rec->scope, "__qualname__"))
|
|
|
|
scope_qualname = rec->scope.attr("__qualname__");
|
2016-07-11 21:40:28 +00:00
|
|
|
object ht_qualname;
|
|
|
|
if (scope_qualname) {
|
2016-10-28 01:08:15 +00:00
|
|
|
ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat(
|
|
|
|
"%U.%U", scope_qualname.ptr(), name.ptr()));
|
2016-07-11 21:40:28 +00:00
|
|
|
} else {
|
|
|
|
ht_qualname = name;
|
|
|
|
}
|
|
|
|
#endif
|
2016-09-11 11:00:40 +00:00
|
|
|
|
|
|
|
size_t num_bases = rec->bases.size();
|
2016-10-25 20:12:39 +00:00
|
|
|
auto bases = tuple(rec->bases);
|
2016-09-11 11:00:40 +00:00
|
|
|
|
2016-10-25 20:12:39 +00:00
|
|
|
std::string full_name = (scope_module ? ((std::string) pybind11::str(scope_module) + "." + rec->name)
|
2016-07-11 21:40:28 +00:00
|
|
|
: std::string(rec->name));
|
|
|
|
|
|
|
|
char *tp_doc = nullptr;
|
2016-11-15 11:38:05 +00:00
|
|
|
if (rec->doc && options::show_user_defined_docstrings()) {
|
2016-07-11 21:40:28 +00:00
|
|
|
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
|
|
|
Python will free this later on) */
|
|
|
|
size_t size = strlen(rec->doc) + 1;
|
|
|
|
tp_doc = (char *) PyObject_MALLOC(size);
|
|
|
|
memcpy((void *) tp_doc, rec->doc, size);
|
|
|
|
}
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/* Danger zone: from now (and until PyType_Ready), make sure to
|
|
|
|
issue no Python C API calls which could potentially invoke the
|
|
|
|
garbage collector (the GC will call type_traverse(), which will in
|
|
|
|
turn find the newly constructed type in an invalid state) */
|
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0));
|
2016-01-17 21:36:41 +00:00
|
|
|
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
|
|
|
|
|
|
|
if (!type_holder || !name)
|
2016-09-14 15:39:16 +00:00
|
|
|
pybind11_fail(std::string(rec->name) + ": Unable to create type object!");
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Register supplemental type information in C++ dict */
|
|
|
|
detail::type_info *tinfo = new detail::type_info();
|
|
|
|
tinfo->type = (PyTypeObject *) type;
|
2016-01-17 21:36:44 +00:00
|
|
|
tinfo->type_size = rec->type_size;
|
|
|
|
tinfo->init_holder = rec->init_holder;
|
2016-10-23 14:27:13 +00:00
|
|
|
tinfo->direct_conversions = &internals.direct_conversions[tindex];
|
2016-05-31 07:53:28 +00:00
|
|
|
internals.registered_types_cpp[tindex] = tinfo;
|
2016-01-17 21:36:41 +00:00
|
|
|
internals.registered_types_py[type] = tinfo;
|
|
|
|
|
|
|
|
/* Basic type attributes */
|
|
|
|
type->ht_type.tp_name = strdup(full_name.c_str());
|
2016-05-29 11:40:40 +00:00
|
|
|
type->ht_type.tp_basicsize = (ssize_t) rec->instance_size;
|
2016-09-11 11:00:40 +00:00
|
|
|
|
|
|
|
if (num_bases > 0) {
|
|
|
|
type->ht_type.tp_base = (PyTypeObject *) ((object) bases[0]).inc_ref().ptr();
|
|
|
|
type->ht_type.tp_bases = bases.release().ptr();
|
|
|
|
rec->multiple_inheritance |= num_bases > 1;
|
|
|
|
}
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-07-11 21:40:28 +00:00
|
|
|
type->ht_name = name.release().ptr();
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
2016-07-11 21:40:28 +00:00
|
|
|
type->ht_qualname = ht_qualname.release().ptr();
|
2015-09-04 21:42:12 +00:00
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Supported protocols */
|
|
|
|
type->ht_type.tp_as_number = &type->as_number;
|
|
|
|
type->ht_type.tp_as_sequence = &type->as_sequence;
|
|
|
|
type->ht_type.tp_as_mapping = &type->as_mapping;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Supported elementary operations */
|
2015-07-05 18:05:44 +00:00
|
|
|
type->ht_type.tp_init = (initproc) init;
|
|
|
|
type->ht_type.tp_new = (newfunc) new_instance;
|
2016-01-17 21:36:44 +00:00
|
|
|
type->ht_type.tp_dealloc = rec->dealloc;
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Support weak references (needed for the keep_alive feature) */
|
2016-01-20 00:26:42 +00:00
|
|
|
type->ht_type.tp_weaklistoffset = offsetof(instance_essentials<void>, weakrefs);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Flags */
|
|
|
|
type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
2015-09-04 21:42:12 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
type->ht_type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
|
|
|
|
#endif
|
2016-01-17 21:36:41 +00:00
|
|
|
type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
|
2016-01-17 21:36:39 +00:00
|
|
|
|
2016-10-10 23:12:48 +00:00
|
|
|
/* Support dynamic attributes */
|
|
|
|
if (rec->dynamic_attr) {
|
|
|
|
type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_GC;
|
2016-10-12 21:20:32 +00:00
|
|
|
type->ht_type.tp_dictoffset = type->ht_type.tp_basicsize; // place the dict at the end
|
|
|
|
type->ht_type.tp_basicsize += sizeof(PyObject *); // and allocate enough space for it
|
2016-10-10 23:12:48 +00:00
|
|
|
type->ht_type.tp_getset = generic_getset;
|
|
|
|
type->ht_type.tp_traverse = traverse;
|
|
|
|
type->ht_type.tp_clear = clear;
|
|
|
|
}
|
|
|
|
|
2016-07-11 21:40:28 +00:00
|
|
|
type->ht_type.tp_doc = tp_doc;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
|
|
|
if (PyType_Ready(&type->ht_type) < 0)
|
2016-09-14 15:39:16 +00:00
|
|
|
pybind11_fail(std::string(rec->name) + ": PyType_Ready failed (" +
|
|
|
|
detail::error_string() + ")!");
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
m_ptr = type_holder.ptr();
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
if (scope_module) // Needed by pydoc
|
2016-01-17 21:36:44 +00:00
|
|
|
attr("__module__") = scope_module;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Register type with the parent scope */
|
2016-04-13 21:33:00 +00:00
|
|
|
if (rec->scope)
|
|
|
|
rec->scope.attr(handle(type->ht_name)) = *this;
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
if (rec->multiple_inheritance)
|
|
|
|
mark_parents_nonsimple(&type->ht_type);
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
type_holder.release();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/// Helper function which tags all parents of a type using mult. inheritance
|
|
|
|
void mark_parents_nonsimple(PyTypeObject *value) {
|
2016-10-28 01:08:15 +00:00
|
|
|
auto t = reinterpret_borrow<tuple>(value->tp_bases);
|
2016-09-11 11:00:40 +00:00
|
|
|
for (handle h : t) {
|
|
|
|
auto tinfo2 = get_type_info((PyTypeObject *) h.ptr());
|
|
|
|
if (tinfo2)
|
|
|
|
tinfo2->simple_type = false;
|
|
|
|
mark_parents_nonsimple((PyTypeObject *) h.ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/// Allocate a metaclass on demand (for static properties)
|
2015-07-05 18:05:44 +00:00
|
|
|
handle metaclass() {
|
|
|
|
auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type;
|
2016-01-17 21:36:41 +00:00
|
|
|
auto &ob_type = PYBIND11_OB_TYPE(ht_type);
|
2015-09-04 21:42:12 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
if (ob_type == &PyType_Type) {
|
2016-01-17 21:36:41 +00:00
|
|
|
std::string name_ = std::string(ht_type.tp_name) + "__Meta";
|
2016-07-11 21:40:28 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
2016-10-28 01:08:15 +00:00
|
|
|
auto ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat("%U__Meta", attr("__qualname__").ptr()));
|
2016-07-11 21:40:28 +00:00
|
|
|
#endif
|
2016-10-28 01:08:15 +00:00
|
|
|
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(name_.c_str()));
|
|
|
|
auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0));
|
2016-01-17 21:36:41 +00:00
|
|
|
if (!type_holder || !name)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("generic_type::metaclass(): unable to create type object!");
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
2016-01-17 21:36:44 +00:00
|
|
|
type->ht_name = name.release().ptr();
|
2016-07-11 21:40:28 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
|
|
|
/* Qualified names for Python >= 3.3 */
|
2016-07-11 21:40:28 +00:00
|
|
|
type->ht_qualname = ht_qualname.release().ptr();
|
2016-01-17 21:36:44 +00:00
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
type->ht_type.tp_name = strdup(name_.c_str());
|
2016-01-17 21:36:44 +00:00
|
|
|
type->ht_type.tp_base = ob_type;
|
2016-01-17 21:36:41 +00:00
|
|
|
type->ht_type.tp_flags |= (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE) &
|
|
|
|
~Py_TPFLAGS_HAVE_GC;
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
if (PyType_Ready(&type->ht_type) < 0)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("generic_type::metaclass(): PyType_Ready failed!");
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
ob_type = (PyTypeObject *) type_holder.release().ptr();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
return handle((PyObject *) ob_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int init(void *self, PyObject *, PyObject *) {
|
|
|
|
std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!";
|
|
|
|
PyErr_SetString(PyExc_TypeError, msg.c_str());
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) {
|
2016-01-17 21:36:41 +00:00
|
|
|
instance<void> *self = (instance<void> *) PyType_GenericAlloc((PyTypeObject *) type, 0);
|
|
|
|
auto tinfo = detail::get_type_info(type);
|
|
|
|
self->value = ::operator new(tinfo->type_size);
|
2015-07-05 18:05:44 +00:00
|
|
|
self->owned = true;
|
Don't construct unique_ptr around unowned pointers (#478)
If we need to initialize a holder around an unowned instance, and the
holder type is non-copyable (i.e. a unique_ptr), we currently construct
the holder type around the value pointer, but then never actually
destruct the holder: the holder destructor is called only for the
instance that actually has `inst->owned = true` set.
This seems no pointer, however, in creating such a holder around an
unowned instance: we never actually intend to use anything that the
unique_ptr gives us: and, in fact, do not want the unique_ptr (because
if it ever actually got destroyed, it would cause destruction of the
wrapped pointer, despite the fact that that wrapped pointer isn't
owned).
This commit changes the logic to only create a unique_ptr holder if we
actually own the instance, and to destruct via the constructed holder
whenever we have a constructed holder--which will now only be the case
for owned-unique-holder or shared-holder types.
Other changes include:
* Added test for non-movable holder constructor/destructor counts
The three alive assertions now pass, before #478 they fail with counts
of 2/2/1 respectively, because of the unique_ptr that we don't want and
don't destroy (because we don't *want* its destructor to run).
* Return cstats reference; fix ConstructStats doc
Small cleanup to the #478 test code, and fix to the ConstructStats
documentation (the static method definition should use `reference` not
`reference_internal`).
* Rename inst->constructed to inst->holder_constructed
This makes it clearer exactly what it's referring to.
2016-11-06 18:12:48 +00:00
|
|
|
self->holder_constructed = false;
|
2016-08-09 21:57:59 +00:00
|
|
|
detail::get_internals().registered_instances.emplace(self->value, (PyObject *) self);
|
2015-07-05 18:05:44 +00:00
|
|
|
return (PyObject *) self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dealloc(instance<void> *self) {
|
|
|
|
if (self->value) {
|
2016-08-09 21:57:59 +00:00
|
|
|
auto instance_type = Py_TYPE(self);
|
|
|
|
auto ®istered_instances = detail::get_internals().registered_instances;
|
|
|
|
auto range = registered_instances.equal_range(self->value);
|
|
|
|
bool found = false;
|
|
|
|
for (auto it = range.first; it != range.second; ++it) {
|
|
|
|
if (instance_type == Py_TYPE(it->second)) {
|
|
|
|
registered_instances.erase(it);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2016-08-09 21:57:59 +00:00
|
|
|
if (!found)
|
|
|
|
pybind11_fail("generic_type::dealloc(): Tried to deallocate unregistered instance!");
|
|
|
|
|
2016-01-17 21:36:39 +00:00
|
|
|
if (self->weakrefs)
|
|
|
|
PyObject_ClearWeakRefs((PyObject *) self);
|
2016-10-10 23:12:48 +00:00
|
|
|
|
2016-10-12 21:20:32 +00:00
|
|
|
PyObject **dict_ptr = _PyObject_GetDictPtr((PyObject *) self);
|
|
|
|
if (dict_ptr) {
|
|
|
|
Py_CLEAR(*dict_ptr);
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
Py_TYPE(self)->tp_free((PyObject*) self);
|
|
|
|
}
|
|
|
|
|
2016-10-10 23:12:48 +00:00
|
|
|
static int traverse(PyObject *op, visitproc visit, void *arg) {
|
2016-10-12 21:20:32 +00:00
|
|
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
|
|
|
Py_VISIT(dict);
|
2016-10-10 23:12:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int clear(PyObject *op) {
|
2016-10-12 21:20:32 +00:00
|
|
|
PyObject *&dict = *_PyObject_GetDictPtr(op);
|
|
|
|
Py_CLEAR(dict);
|
2016-10-10 23:12:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-28 14:12:20 +00:00
|
|
|
void install_buffer_funcs(
|
|
|
|
buffer_info *(*get_buffer)(PyObject *, void *),
|
|
|
|
void *get_buffer_data) {
|
2015-07-05 18:05:44 +00:00
|
|
|
PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr;
|
|
|
|
type->ht_type.tp_as_buffer = &type->as_buffer;
|
2015-09-04 21:42:12 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
|
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
type->as_buffer.bf_getbuffer = getbuffer;
|
|
|
|
type->as_buffer.bf_releasebuffer = releasebuffer;
|
2016-01-17 21:36:41 +00:00
|
|
|
auto tinfo = detail::get_type_info(&type->ht_type);
|
|
|
|
tinfo->get_buffer = get_buffer;
|
|
|
|
tinfo->get_buffer_data = get_buffer_data;
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
|
2016-01-17 21:36:41 +00:00
|
|
|
auto tinfo = detail::get_type_info(Py_TYPE(obj));
|
|
|
|
if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer) {
|
|
|
|
PyErr_SetString(PyExc_BufferError, "generic_type::getbuffer(): Internal error");
|
2015-07-05 18:05:44 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
memset(view, 0, sizeof(Py_buffer));
|
2016-01-17 21:36:41 +00:00
|
|
|
buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
|
2015-07-05 18:05:44 +00:00
|
|
|
view->obj = obj;
|
|
|
|
view->ndim = 1;
|
|
|
|
view->internal = info;
|
|
|
|
view->buf = info->ptr;
|
2016-05-29 11:40:40 +00:00
|
|
|
view->itemsize = (ssize_t) info->itemsize;
|
2015-07-05 18:05:44 +00:00
|
|
|
view->len = view->itemsize;
|
|
|
|
for (auto s : info->shape)
|
|
|
|
view->len *= s;
|
|
|
|
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
|
|
|
|
view->format = const_cast<char *>(info->format.c_str());
|
|
|
|
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
|
2016-05-29 11:40:40 +00:00
|
|
|
view->ndim = (int) info->ndim;
|
2016-01-17 21:36:37 +00:00
|
|
|
view->strides = (ssize_t *) &info->strides[0];
|
|
|
|
view->shape = (ssize_t *) &info->shape[0];
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
Py_INCREF(view->obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
|
|
|
|
};
|
2016-09-06 16:27:00 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
NAMESPACE_END(detail)
|
|
|
|
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename type_, typename... options>
|
2016-01-17 21:36:44 +00:00
|
|
|
class class_ : public detail::generic_type {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename T> using is_holder = detail::is_holder_type<type_, T>;
|
|
|
|
template <typename T> using is_subtype = detail::bool_constant<std::is_base_of<type_, T>::value && !std::is_same<T, type_>::value>;
|
2016-09-11 11:00:40 +00:00
|
|
|
template <typename T> using is_base = detail::bool_constant<std::is_base_of<T, type_>::value && !std::is_same<T, type_>::value>;
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename T> using is_valid_class_option =
|
|
|
|
detail::bool_constant<
|
|
|
|
is_holder<T>::value ||
|
2016-09-06 16:27:00 +00:00
|
|
|
is_subtype<T>::value ||
|
2016-09-11 11:00:40 +00:00
|
|
|
is_base<T>::value
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
>;
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
using type = type_;
|
2016-09-06 16:27:00 +00:00
|
|
|
using type_alias = detail::first_of_t<is_subtype, void, options...>;
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
constexpr static bool has_alias = !std::is_void<type_alias>::value;
|
2016-09-06 16:27:00 +00:00
|
|
|
using holder_type = detail::first_of_t<is_holder, std::unique_ptr<type>, options...>;
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
using instance_type = detail::instance<type, holder_type>;
|
|
|
|
|
|
|
|
static_assert(detail::all_of_t<is_valid_class_option, options...>::value,
|
|
|
|
"Unknown/invalid class_ template parameters provided");
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-10-28 01:08:15 +00:00
|
|
|
PYBIND11_OBJECT(class_, generic_type, PyType_Check)
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_(handle scope, const char *name, const Extra &... extra) {
|
|
|
|
detail::type_record record;
|
|
|
|
record.scope = scope;
|
|
|
|
record.name = name;
|
|
|
|
record.type = &typeid(type);
|
2016-09-08 15:03:08 +00:00
|
|
|
record.type_size = sizeof(detail::conditional_t<has_alias, type_alias, type>);
|
2016-01-17 21:36:44 +00:00
|
|
|
record.instance_size = sizeof(instance_type);
|
|
|
|
record.init_holder = init_holder;
|
|
|
|
record.dealloc = dealloc;
|
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
/* Register base classes specified via template arguments to class_, if any */
|
2016-09-12 15:36:43 +00:00
|
|
|
bool unused[] = { (add_base<options>(record), false)..., false };
|
2016-09-11 11:00:40 +00:00
|
|
|
(void) unused;
|
2016-09-06 16:27:00 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
/* Process optional arguments, if any */
|
|
|
|
detail::process_attributes<Extra...>::init(extra..., &record);
|
|
|
|
|
|
|
|
detail::generic_type::initialize(&record);
|
2016-05-26 11:19:27 +00:00
|
|
|
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
if (has_alias) {
|
2016-05-26 11:19:27 +00:00
|
|
|
auto &instances = pybind11::detail::get_internals().registered_types_cpp;
|
|
|
|
instances[std::type_index(typeid(type_alias))] = instances[std::type_index(typeid(type))];
|
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-09-12 15:36:43 +00:00
|
|
|
template <typename Base, detail::enable_if_t<is_base<Base>::value, int> = 0>
|
2016-09-11 11:00:40 +00:00
|
|
|
static void add_base(detail::type_record &rec) {
|
|
|
|
rec.add_base(&typeid(Base), [](void *src) -> void * {
|
|
|
|
return static_cast<Base *>(reinterpret_cast<type *>(src));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-09-12 15:36:43 +00:00
|
|
|
template <typename Base, detail::enable_if_t<!is_base<Base>::value, int> = 0>
|
2016-09-11 11:00:40 +00:00
|
|
|
static void add_base(detail::type_record &) { }
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Func, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def(const char *name_, Func&& f, const Extra&... extra) {
|
2016-09-20 23:06:32 +00:00
|
|
|
cpp_function cf(std::forward<Func>(f), name(name_), is_method(*this),
|
|
|
|
sibling(getattr(*this, name_, none())), extra...);
|
2015-09-04 21:42:12 +00:00
|
|
|
attr(cf.name()) = cf;
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Func, typename... Extra> class_ &
|
2016-01-17 21:36:44 +00:00
|
|
|
def_static(const char *name_, Func f, const Extra&... extra) {
|
2016-09-20 23:06:32 +00:00
|
|
|
cpp_function cf(std::forward<Func>(f), name(name_), scope(*this),
|
|
|
|
sibling(getattr(*this, name_, none())), extra...);
|
2015-09-04 21:42:12 +00:00
|
|
|
attr(cf.name()) = cf;
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
op.execute(*this, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ & def_cast(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
op.execute_cast(*this, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename... Args, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def(const detail::init<Args...> &init, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
init.execute(*this, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-05-26 11:19:27 +00:00
|
|
|
template <typename... Args, typename... Extra>
|
|
|
|
class_ &def(const detail::init_alias<Args...> &init, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
init.execute(*this, extra...);
|
2016-05-26 11:19:27 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Func> class_& def_buffer(Func &&func) {
|
2015-07-28 14:12:20 +00:00
|
|
|
struct capture { Func func; };
|
|
|
|
capture *ptr = new capture { std::forward<Func>(func) };
|
|
|
|
install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* {
|
2015-07-05 18:05:44 +00:00
|
|
|
detail::type_caster<type> caster;
|
|
|
|
if (!caster.load(obj, false))
|
|
|
|
return nullptr;
|
2015-07-28 14:12:20 +00:00
|
|
|
return new buffer_info(((capture *) ptr)->func(caster));
|
|
|
|
}, ptr);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename C, typename D, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def_readwrite(const char *name, D C::*pm, const Extra&... extra) {
|
2016-03-25 15:13:10 +00:00
|
|
|
cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)),
|
|
|
|
fset([pm](C &c, const D &value) { c.*pm = value; }, is_method(*this));
|
|
|
|
def_property(name, fget, fset, return_value_policy::reference_internal, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename C, typename D, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def_readonly(const char *name, const D C::*pm, const Extra& ...extra) {
|
2016-03-25 15:13:10 +00:00
|
|
|
cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this));
|
|
|
|
def_property_readonly(name, fget, return_value_policy::reference_internal, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename D, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) {
|
2016-03-25 15:13:10 +00:00
|
|
|
cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this)),
|
|
|
|
fset([pm](object, const D &value) { *pm = value; }, scope(*this));
|
|
|
|
def_property_static(name, fget, fset, return_value_policy::reference, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename D, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) {
|
2016-03-25 15:13:10 +00:00
|
|
|
cpp_function fget([pm](object) -> const D &{ return *pm; }, scope(*this));
|
|
|
|
def_property_readonly_static(name, fget, return_value_policy::reference, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-11-01 10:44:57 +00:00
|
|
|
/// Uses return_value_policy::reference_internal by default
|
|
|
|
template <typename Getter, typename... Extra>
|
|
|
|
class_ &def_property_readonly(const char *name, const Getter &fget, const Extra& ...extra) {
|
|
|
|
return def_property_readonly(name, cpp_function(fget), return_value_policy::reference_internal, extra...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Uses cpp_function's return_value_policy by default
|
2016-03-21 16:54:24 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_ &def_property_readonly(const char *name, const cpp_function &fget, const Extra& ...extra) {
|
2016-11-01 10:44:57 +00:00
|
|
|
return def_property(name, fget, cpp_function(), extra...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Uses return_value_policy::reference by default
|
|
|
|
template <typename Getter, typename... Extra>
|
|
|
|
class_ &def_property_readonly_static(const char *name, const Getter &fget, const Extra& ...extra) {
|
|
|
|
return def_property_readonly_static(name, cpp_function(fget), return_value_policy::reference, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-01 10:44:57 +00:00
|
|
|
/// Uses cpp_function's return_value_policy by default
|
2016-03-21 16:54:24 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_ &def_property_readonly_static(const char *name, const cpp_function &fget, const Extra& ...extra) {
|
2016-11-01 10:44:57 +00:00
|
|
|
return def_property_static(name, fget, cpp_function(), extra...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Uses return_value_policy::reference_internal by default
|
|
|
|
template <typename Getter, typename... Extra>
|
|
|
|
class_ &def_property(const char *name, const Getter &fget, const cpp_function &fset, const Extra& ...extra) {
|
|
|
|
return def_property(name, cpp_function(fget), fset, return_value_policy::reference_internal, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-01 10:44:57 +00:00
|
|
|
/// Uses cpp_function's return_value_policy by default
|
2016-03-21 16:54:24 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) {
|
2016-03-25 15:13:10 +00:00
|
|
|
return def_property_static(name, fget, fset, is_method(*this), extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-11-01 10:44:57 +00:00
|
|
|
/// Uses return_value_policy::reference by default
|
|
|
|
template <typename Getter, typename... Extra>
|
|
|
|
class_ &def_property_static(const char *name, const Getter &fget, const cpp_function &fset, const Extra& ...extra) {
|
|
|
|
return def_property_static(name, cpp_function(fget), fset, return_value_policy::reference, extra...);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Uses cpp_function's return_value_policy by default
|
2016-03-21 16:54:24 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset, const Extra& ...extra) {
|
|
|
|
auto rec_fget = get_function_record(fget), rec_fset = get_function_record(fset);
|
2016-06-02 18:33:01 +00:00
|
|
|
char *doc_prev = rec_fget->doc; /* 'extra' field may include a property-specific documentation string */
|
2016-03-21 16:54:24 +00:00
|
|
|
detail::process_attributes<Extra...>::init(extra..., rec_fget);
|
2016-06-02 18:33:01 +00:00
|
|
|
if (rec_fget->doc && rec_fget->doc != doc_prev) {
|
|
|
|
free(doc_prev);
|
|
|
|
rec_fget->doc = strdup(rec_fget->doc);
|
|
|
|
}
|
|
|
|
if (rec_fset) {
|
|
|
|
doc_prev = rec_fset->doc;
|
2016-03-21 16:54:24 +00:00
|
|
|
detail::process_attributes<Extra...>::init(extra..., rec_fset);
|
2016-06-02 18:33:01 +00:00
|
|
|
if (rec_fset->doc && rec_fset->doc != doc_prev) {
|
|
|
|
free(doc_prev);
|
|
|
|
rec_fset->doc = strdup(rec_fset->doc);
|
|
|
|
}
|
|
|
|
}
|
2016-11-15 11:38:05 +00:00
|
|
|
pybind11::str doc_obj = pybind11::str((rec_fget->doc && pybind11::options::show_user_defined_docstrings()) ? rec_fget->doc : "");
|
2016-10-28 01:08:15 +00:00
|
|
|
const auto property = reinterpret_steal<object>(
|
2016-01-17 21:36:44 +00:00
|
|
|
PyObject_CallFunctionObjArgs((PyObject *) &PyProperty_Type, fget.ptr() ? fget.ptr() : Py_None,
|
2016-10-28 01:08:15 +00:00
|
|
|
fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr));
|
2016-03-21 16:54:24 +00:00
|
|
|
if (rec_fget->class_)
|
|
|
|
attr(name) = property;
|
|
|
|
else
|
|
|
|
metaclass().attr(name) = property;
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-10-01 14:46:03 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
private:
|
2016-01-17 21:36:40 +00:00
|
|
|
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
|
|
|
|
template <typename T>
|
|
|
|
static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) {
|
2015-11-24 22:05:58 +00:00
|
|
|
try {
|
2016-07-01 10:39:55 +00:00
|
|
|
new (&inst->holder) holder_type(std::static_pointer_cast<typename holder_type::element_type>(inst->value->shared_from_this()));
|
2015-11-24 22:05:58 +00:00
|
|
|
} catch (const std::bad_weak_ptr &) {
|
|
|
|
new (&inst->holder) holder_type(inst->value);
|
|
|
|
}
|
Don't construct unique_ptr around unowned pointers (#478)
If we need to initialize a holder around an unowned instance, and the
holder type is non-copyable (i.e. a unique_ptr), we currently construct
the holder type around the value pointer, but then never actually
destruct the holder: the holder destructor is called only for the
instance that actually has `inst->owned = true` set.
This seems no pointer, however, in creating such a holder around an
unowned instance: we never actually intend to use anything that the
unique_ptr gives us: and, in fact, do not want the unique_ptr (because
if it ever actually got destroyed, it would cause destruction of the
wrapped pointer, despite the fact that that wrapped pointer isn't
owned).
This commit changes the logic to only create a unique_ptr holder if we
actually own the instance, and to destruct via the constructed holder
whenever we have a constructed holder--which will now only be the case
for owned-unique-holder or shared-holder types.
Other changes include:
* Added test for non-movable holder constructor/destructor counts
The three alive assertions now pass, before #478 they fail with counts
of 2/2/1 respectively, because of the unique_ptr that we don't want and
don't destroy (because we don't *want* its destructor to run).
* Return cstats reference; fix ConstructStats doc
Small cleanup to the #478 test code, and fix to the ConstructStats
documentation (the static method definition should use `reference` not
`reference_internal`).
* Rename inst->constructed to inst->holder_constructed
This makes it clearer exactly what it's referring to.
2016-11-06 18:12:48 +00:00
|
|
|
inst->holder_constructed = true;
|
2016-01-17 21:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
|
|
|
|
template <typename T = holder_type,
|
2016-09-12 15:36:43 +00:00
|
|
|
detail::enable_if_t<std::is_copy_constructible<T>::value, int> = 0>
|
2016-01-17 21:36:40 +00:00
|
|
|
static void init_holder_helper(instance_type *inst, const holder_type *holder_ptr, const void * /* dummy */) {
|
|
|
|
if (holder_ptr)
|
|
|
|
new (&inst->holder) holder_type(*holder_ptr);
|
|
|
|
else
|
|
|
|
new (&inst->holder) holder_type(inst->value);
|
Don't construct unique_ptr around unowned pointers (#478)
If we need to initialize a holder around an unowned instance, and the
holder type is non-copyable (i.e. a unique_ptr), we currently construct
the holder type around the value pointer, but then never actually
destruct the holder: the holder destructor is called only for the
instance that actually has `inst->owned = true` set.
This seems no pointer, however, in creating such a holder around an
unowned instance: we never actually intend to use anything that the
unique_ptr gives us: and, in fact, do not want the unique_ptr (because
if it ever actually got destroyed, it would cause destruction of the
wrapped pointer, despite the fact that that wrapped pointer isn't
owned).
This commit changes the logic to only create a unique_ptr holder if we
actually own the instance, and to destruct via the constructed holder
whenever we have a constructed holder--which will now only be the case
for owned-unique-holder or shared-holder types.
Other changes include:
* Added test for non-movable holder constructor/destructor counts
The three alive assertions now pass, before #478 they fail with counts
of 2/2/1 respectively, because of the unique_ptr that we don't want and
don't destroy (because we don't *want* its destructor to run).
* Return cstats reference; fix ConstructStats doc
Small cleanup to the #478 test code, and fix to the ConstructStats
documentation (the static method definition should use `reference` not
`reference_internal`).
* Rename inst->constructed to inst->holder_constructed
This makes it clearer exactly what it's referring to.
2016-11-06 18:12:48 +00:00
|
|
|
inst->holder_constructed = true;
|
2016-01-17 21:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer
|
|
|
|
template <typename T = holder_type,
|
2016-09-12 15:36:43 +00:00
|
|
|
detail::enable_if_t<!std::is_copy_constructible<T>::value, int> = 0>
|
2016-01-17 21:36:40 +00:00
|
|
|
static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const void * /* dummy */) {
|
Don't construct unique_ptr around unowned pointers (#478)
If we need to initialize a holder around an unowned instance, and the
holder type is non-copyable (i.e. a unique_ptr), we currently construct
the holder type around the value pointer, but then never actually
destruct the holder: the holder destructor is called only for the
instance that actually has `inst->owned = true` set.
This seems no pointer, however, in creating such a holder around an
unowned instance: we never actually intend to use anything that the
unique_ptr gives us: and, in fact, do not want the unique_ptr (because
if it ever actually got destroyed, it would cause destruction of the
wrapped pointer, despite the fact that that wrapped pointer isn't
owned).
This commit changes the logic to only create a unique_ptr holder if we
actually own the instance, and to destruct via the constructed holder
whenever we have a constructed holder--which will now only be the case
for owned-unique-holder or shared-holder types.
Other changes include:
* Added test for non-movable holder constructor/destructor counts
The three alive assertions now pass, before #478 they fail with counts
of 2/2/1 respectively, because of the unique_ptr that we don't want and
don't destroy (because we don't *want* its destructor to run).
* Return cstats reference; fix ConstructStats doc
Small cleanup to the #478 test code, and fix to the ConstructStats
documentation (the static method definition should use `reference` not
`reference_internal`).
* Rename inst->constructed to inst->holder_constructed
This makes it clearer exactly what it's referring to.
2016-11-06 18:12:48 +00:00
|
|
|
if (inst->owned) {
|
|
|
|
new (&inst->holder) holder_type(inst->value);
|
|
|
|
inst->holder_constructed = true;
|
|
|
|
}
|
2016-01-17 21:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize holder object of an instance, possibly given a pointer to an existing holder
|
|
|
|
static void init_holder(PyObject *inst_, const void *holder_ptr) {
|
|
|
|
auto inst = (instance_type *) inst_;
|
|
|
|
init_holder_helper(inst, (const holder_type *) holder_ptr, inst->value);
|
2015-11-24 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
static void dealloc(PyObject *inst_) {
|
|
|
|
instance_type *inst = (instance_type *) inst_;
|
Don't construct unique_ptr around unowned pointers (#478)
If we need to initialize a holder around an unowned instance, and the
holder type is non-copyable (i.e. a unique_ptr), we currently construct
the holder type around the value pointer, but then never actually
destruct the holder: the holder destructor is called only for the
instance that actually has `inst->owned = true` set.
This seems no pointer, however, in creating such a holder around an
unowned instance: we never actually intend to use anything that the
unique_ptr gives us: and, in fact, do not want the unique_ptr (because
if it ever actually got destroyed, it would cause destruction of the
wrapped pointer, despite the fact that that wrapped pointer isn't
owned).
This commit changes the logic to only create a unique_ptr holder if we
actually own the instance, and to destruct via the constructed holder
whenever we have a constructed holder--which will now only be the case
for owned-unique-holder or shared-holder types.
Other changes include:
* Added test for non-movable holder constructor/destructor counts
The three alive assertions now pass, before #478 they fail with counts
of 2/2/1 respectively, because of the unique_ptr that we don't want and
don't destroy (because we don't *want* its destructor to run).
* Return cstats reference; fix ConstructStats doc
Small cleanup to the #478 test code, and fix to the ConstructStats
documentation (the static method definition should use `reference` not
`reference_internal`).
* Rename inst->constructed to inst->holder_constructed
This makes it clearer exactly what it's referring to.
2016-11-06 18:12:48 +00:00
|
|
|
if (inst->holder_constructed)
|
|
|
|
inst->holder.~holder_type();
|
|
|
|
else if (inst->owned)
|
|
|
|
::operator delete(inst->value);
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
generic_type::dealloc((detail::instance<void> *) inst);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
2016-03-21 16:54:24 +00:00
|
|
|
|
|
|
|
static detail::function_record *get_function_record(handle h) {
|
|
|
|
h = detail::get_function(h);
|
2016-10-28 01:08:15 +00:00
|
|
|
return h ? (detail::function_record *) reinterpret_borrow<capsule>(PyCFunction_GetSelf(h.ptr()))
|
|
|
|
: nullptr;
|
2016-03-21 16:54:24 +00:00
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Binds C++ enumerations and enumeration classes to Python
|
|
|
|
template <typename Type> class enum_ : public class_<Type> {
|
|
|
|
public:
|
2016-09-05 08:20:50 +00:00
|
|
|
using class_<Type>::def;
|
2016-11-17 22:24:47 +00:00
|
|
|
using Scalar = typename std::underlying_type<Type>::type;
|
|
|
|
template <typename T> using arithmetic_tag = std::is_same<T, arithmetic>;
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
enum_(const handle &scope, const char *name, const Extra&... extra)
|
|
|
|
: class_<Type>(scope, name, extra...), m_parent(scope) {
|
2016-11-17 22:24:47 +00:00
|
|
|
|
|
|
|
constexpr bool is_arithmetic =
|
|
|
|
!std::is_same<detail::first_of_t<arithmetic_tag, void, Extra...>,
|
|
|
|
void>::value;
|
|
|
|
|
|
|
|
auto entries = new std::unordered_map<Scalar, const char *>();
|
2016-09-05 08:20:50 +00:00
|
|
|
def("__repr__", [name, entries](Type value) -> std::string {
|
2016-11-17 22:24:47 +00:00
|
|
|
auto it = entries->find((Scalar) value);
|
2015-07-05 18:05:44 +00:00
|
|
|
return std::string(name) + "." +
|
|
|
|
((it == entries->end()) ? std::string("???")
|
|
|
|
: std::string(it->second));
|
|
|
|
});
|
2016-11-17 22:24:47 +00:00
|
|
|
def("__init__", [](Type& value, Scalar i) { value = (Type)i; });
|
|
|
|
def("__init__", [](Type& value, Scalar i) { new (&value) Type((Type) i); });
|
|
|
|
def("__int__", [](Type value) { return (Scalar) value; });
|
2016-09-05 08:20:50 +00:00
|
|
|
def("__eq__", [](const Type &value, Type *value2) { return value2 && value == *value2; });
|
|
|
|
def("__ne__", [](const Type &value, Type *value2) { return !value2 || value != *value2; });
|
2016-11-17 22:24:47 +00:00
|
|
|
if (is_arithmetic) {
|
|
|
|
def("__lt__", [](const Type &value, Type *value2) { return value2 && value < *value2; });
|
|
|
|
def("__gt__", [](const Type &value, Type *value2) { return value2 && value > *value2; });
|
|
|
|
def("__le__", [](const Type &value, Type *value2) { return value2 && value <= *value2; });
|
|
|
|
def("__ge__", [](const Type &value, Type *value2) { return value2 && value >= *value2; });
|
|
|
|
}
|
|
|
|
if (std::is_convertible<Type, Scalar>::value) {
|
2016-08-04 04:21:37 +00:00
|
|
|
// Don't provide comparison with the underlying type if the enum isn't convertible,
|
|
|
|
// i.e. if Type is a scoped enum, mirroring the C++ behaviour. (NB: we explicitly
|
2016-11-17 22:24:47 +00:00
|
|
|
// convert Type to Scalar below anyway because this needs to compile).
|
|
|
|
def("__eq__", [](const Type &value, Scalar value2) { return (Scalar) value == value2; });
|
|
|
|
def("__ne__", [](const Type &value, Scalar value2) { return (Scalar) value != value2; });
|
|
|
|
if (is_arithmetic) {
|
|
|
|
def("__lt__", [](const Type &value, Scalar value2) { return (Scalar) value < value2; });
|
|
|
|
def("__gt__", [](const Type &value, Scalar value2) { return (Scalar) value > value2; });
|
|
|
|
def("__le__", [](const Type &value, Scalar value2) { return (Scalar) value <= value2; });
|
|
|
|
def("__ge__", [](const Type &value, Scalar value2) { return (Scalar) value >= value2; });
|
|
|
|
def("__invert__", [](const Type &value) { return ~((Scalar) value); });
|
|
|
|
def("__and__", [](const Type &value, Scalar value2) { return (Scalar) value & value2; });
|
|
|
|
def("__or__", [](const Type &value, Scalar value2) { return (Scalar) value | value2; });
|
|
|
|
def("__xor__", [](const Type &value, Scalar value2) { return (Scalar) value ^ value2; });
|
|
|
|
def("__rand__", [](const Type &value, Scalar value2) { return (Scalar) value & value2; });
|
|
|
|
def("__ror__", [](const Type &value, Scalar value2) { return (Scalar) value | value2; });
|
|
|
|
def("__rxor__", [](const Type &value, Scalar value2) { return (Scalar) value ^ value2; });
|
|
|
|
def("__and__", [](const Type &value, const Type &value2) { return (Scalar) value & (Scalar) value2; });
|
|
|
|
def("__or__", [](const Type &value, const Type &value2) { return (Scalar) value | (Scalar) value2; });
|
|
|
|
def("__xor__", [](const Type &value, const Type &value2) { return (Scalar) value ^ (Scalar) value2; });
|
|
|
|
}
|
2016-08-04 04:21:37 +00:00
|
|
|
}
|
2016-11-17 22:24:47 +00:00
|
|
|
def("__hash__", [](const Type &value) { return (Scalar) value; });
|
2016-09-06 04:02:29 +00:00
|
|
|
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
|
2016-11-17 22:24:47 +00:00
|
|
|
def("__getstate__", [](const Type &value) { return pybind11::make_tuple((Scalar) value); });
|
|
|
|
def("__setstate__", [](Type &p, tuple t) { new (&p) Type((Type) t[0].cast<Scalar>()); });
|
2015-07-05 18:05:44 +00:00
|
|
|
m_entries = entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Export enumeration entries into the parent scope
|
2016-11-04 15:51:14 +00:00
|
|
|
enum_ &export_values() {
|
2015-07-05 18:05:44 +00:00
|
|
|
PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
|
|
|
|
PyObject *key, *value;
|
2016-01-17 21:36:37 +00:00
|
|
|
ssize_t pos = 0;
|
2015-07-05 18:05:44 +00:00
|
|
|
while (PyDict_Next(dict, &pos, &key, &value))
|
|
|
|
if (PyObject_IsInstance(value, this->m_ptr))
|
|
|
|
m_parent.attr(key) = value;
|
2016-11-04 15:51:14 +00:00
|
|
|
return *this;
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add an enumeration entry
|
|
|
|
enum_& value(char const* name, Type value) {
|
2015-10-15 16:13:33 +00:00
|
|
|
this->attr(name) = pybind11::cast(value, return_value_policy::copy);
|
2016-11-17 22:24:47 +00:00
|
|
|
(*m_entries)[(Scalar) value] = name;
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
private:
|
2016-11-17 22:24:47 +00:00
|
|
|
std::unordered_map<Scalar, const char *> *m_entries;
|
2016-01-17 21:36:44 +00:00
|
|
|
handle m_parent;
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(detail)
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename... Args> struct init {
|
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 06:42:51 +00:00
|
|
|
template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
|
|
|
|
static void execute(Class &cl, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
using Base = typename Class::type;
|
2015-07-05 18:05:44 +00:00
|
|
|
/// Function which calls a specific C++ in-place constructor
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
cl.def("__init__", [](Base *self_, Args... args) { new (self_) Base(args...); }, extra...);
|
2016-05-26 11:19:27 +00:00
|
|
|
}
|
|
|
|
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename Class, typename... Extra,
|
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 06:42:51 +00:00
|
|
|
enable_if_t<Class::has_alias &&
|
|
|
|
std::is_constructible<typename Class::type, Args...>::value, int> = 0>
|
|
|
|
static void execute(Class &cl, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
using Base = typename Class::type;
|
|
|
|
using Alias = typename Class::type_alias;
|
|
|
|
handle cl_type = cl;
|
|
|
|
cl.def("__init__", [cl_type](handle self_, Args... args) {
|
2016-05-26 12:29:31 +00:00
|
|
|
if (self_.get_type() == cl_type)
|
|
|
|
new (self_.cast<Base *>()) Base(args...);
|
2016-05-26 11:19:27 +00:00
|
|
|
else
|
2016-05-26 12:29:31 +00:00
|
|
|
new (self_.cast<Alias *>()) Alias(args...);
|
2016-05-26 11:19:27 +00:00
|
|
|
}, extra...);
|
|
|
|
}
|
|
|
|
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
template <typename Class, typename... Extra,
|
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 06:42:51 +00:00
|
|
|
enable_if_t<Class::has_alias &&
|
|
|
|
!std::is_constructible<typename Class::type, Args...>::value, int> = 0>
|
|
|
|
static void execute(Class &cl, const Extra&... extra) {
|
|
|
|
init_alias<Args...>::execute(cl, extra...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
template <typename... Args> struct init_alias {
|
|
|
|
template <typename Class, typename... Extra,
|
|
|
|
enable_if_t<Class::has_alias && std::is_constructible<typename Class::type_alias, Args...>::value, int> = 0>
|
|
|
|
static void execute(Class &cl, const Extra&... extra) {
|
Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.
This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options. It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively. (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively). If any unmatched template arguments are provided, a
static assertion fails.
What this means is that you can specify or omit the arguments in any
order:
py::class_<A, PyA> c1(m, "A");
py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");
It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 16:17:06 +00:00
|
|
|
using Alias = typename Class::type_alias;
|
|
|
|
cl.def("__init__", [](Alias *self_, Args... args) { new (self_) Alias(args...); }, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
};
|
2016-01-17 21:36:39 +00:00
|
|
|
|
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 06:42:51 +00:00
|
|
|
|
2016-08-10 16:08:04 +00:00
|
|
|
inline void keep_alive_impl(handle nurse, handle patient) {
|
2016-01-17 21:36:39 +00:00
|
|
|
/* Clever approach based on weak references taken from Boost.Python */
|
2016-01-17 21:36:40 +00:00
|
|
|
if (!nurse || !patient)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("Could not activate keep_alive!");
|
2016-01-17 21:36:39 +00:00
|
|
|
|
2016-08-29 01:38:47 +00:00
|
|
|
if (patient.is_none() || nurse.is_none())
|
2016-08-16 05:50:43 +00:00
|
|
|
return; /* Nothing to keep alive or nothing to be kept alive by */
|
2016-04-25 01:25:13 +00:00
|
|
|
|
2016-01-17 21:36:39 +00:00
|
|
|
cpp_function disable_lifesupport(
|
2016-01-17 21:36:40 +00:00
|
|
|
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
2016-01-17 21:36:39 +00:00
|
|
|
|
2016-01-17 21:36:40 +00:00
|
|
|
weakref wr(nurse, disable_lifesupport);
|
2016-01-17 21:36:39 +00:00
|
|
|
|
2016-01-17 21:36:40 +00:00
|
|
|
patient.inc_ref(); /* reference patient and leak the weak reference */
|
|
|
|
(void) wr.release();
|
2016-01-17 21:36:39 +00:00
|
|
|
}
|
|
|
|
|
2016-08-10 16:08:04 +00:00
|
|
|
PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret) {
|
|
|
|
handle nurse (Nurse > 0 ? PyTuple_GetItem(args.ptr(), Nurse - 1) : ret.ptr());
|
|
|
|
handle patient(Patient > 0 ? PyTuple_GetItem(args.ptr(), Patient - 1) : ret.ptr());
|
|
|
|
|
|
|
|
keep_alive_impl(nurse, patient);
|
|
|
|
}
|
|
|
|
|
2016-09-10 07:00:50 +00:00
|
|
|
template <typename Iterator, typename Sentinel, bool KeyIterator, return_value_policy Policy>
|
2016-08-24 22:29:04 +00:00
|
|
|
struct iterator_state {
|
|
|
|
Iterator it;
|
|
|
|
Sentinel end;
|
2016-06-17 21:29:39 +00:00
|
|
|
bool first;
|
|
|
|
};
|
2016-04-13 21:33:00 +00:00
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
NAMESPACE_END(detail)
|
|
|
|
|
2016-02-18 18:20:15 +00:00
|
|
|
template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); }
|
Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`. Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias. py::init_alias<>, in contrast, always invokes the
constructor of the alias type.
It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f3302701d81414ddd3d38bcd09433076bc, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.
This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 06:42:51 +00:00
|
|
|
template <typename... Args> detail::init_alias<Args...> init_alias() { return detail::init_alias<Args...>(); }
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-09-10 07:00:50 +00:00
|
|
|
template <return_value_policy Policy = return_value_policy::reference_internal,
|
|
|
|
typename Iterator,
|
2016-08-24 22:29:04 +00:00
|
|
|
typename Sentinel,
|
2016-05-30 09:28:21 +00:00
|
|
|
typename ValueType = decltype(*std::declval<Iterator>()),
|
|
|
|
typename... Extra>
|
2016-08-24 22:29:04 +00:00
|
|
|
iterator make_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
2016-09-10 07:00:50 +00:00
|
|
|
typedef detail::iterator_state<Iterator, Sentinel, false, Policy> state;
|
2016-04-13 21:33:00 +00:00
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
if (!detail::get_type_info(typeid(state), false)) {
|
2016-09-06 04:06:31 +00:00
|
|
|
class_<state>(handle(), "iterator")
|
2016-04-13 21:33:00 +00:00
|
|
|
.def("__iter__", [](state &s) -> state& { return s; })
|
2016-05-30 09:28:21 +00:00
|
|
|
.def("__next__", [](state &s) -> ValueType {
|
2016-06-17 21:29:39 +00:00
|
|
|
if (!s.first)
|
|
|
|
++s.it;
|
|
|
|
else
|
|
|
|
s.first = false;
|
2016-04-13 21:33:00 +00:00
|
|
|
if (s.it == s.end)
|
|
|
|
throw stop_iteration();
|
2016-06-17 21:29:39 +00:00
|
|
|
return *s.it;
|
2016-09-10 07:00:50 +00:00
|
|
|
}, std::forward<Extra>(extra)..., Policy);
|
2016-04-13 21:33:00 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 21:29:39 +00:00
|
|
|
return (iterator) cast(state { first, last, true });
|
2016-04-13 21:33:00 +00:00
|
|
|
}
|
2016-09-06 04:06:31 +00:00
|
|
|
|
2016-09-10 07:00:50 +00:00
|
|
|
template <return_value_policy Policy = return_value_policy::reference_internal,
|
|
|
|
typename Iterator,
|
2016-08-24 22:29:04 +00:00
|
|
|
typename Sentinel,
|
2016-08-24 22:27:19 +00:00
|
|
|
typename KeyType = decltype((*std::declval<Iterator>()).first),
|
2016-08-12 01:22:05 +00:00
|
|
|
typename... Extra>
|
2016-08-24 22:29:04 +00:00
|
|
|
iterator make_key_iterator(Iterator first, Sentinel last, Extra &&... extra) {
|
2016-09-10 07:00:50 +00:00
|
|
|
typedef detail::iterator_state<Iterator, Sentinel, true, Policy> state;
|
2016-08-12 01:22:05 +00:00
|
|
|
|
2016-09-11 11:00:40 +00:00
|
|
|
if (!detail::get_type_info(typeid(state), false)) {
|
2016-09-06 04:06:31 +00:00
|
|
|
class_<state>(handle(), "iterator")
|
2016-08-12 01:22:05 +00:00
|
|
|
.def("__iter__", [](state &s) -> state& { return s; })
|
|
|
|
.def("__next__", [](state &s) -> KeyType {
|
|
|
|
if (!s.first)
|
|
|
|
++s.it;
|
|
|
|
else
|
|
|
|
s.first = false;
|
|
|
|
if (s.it == s.end)
|
|
|
|
throw stop_iteration();
|
2016-08-24 22:27:19 +00:00
|
|
|
return (*s.it).first;
|
2016-09-10 07:00:50 +00:00
|
|
|
}, std::forward<Extra>(extra)..., Policy);
|
2016-08-12 01:22:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (iterator) cast(state { first, last, true });
|
|
|
|
}
|
2016-04-13 21:33:00 +00:00
|
|
|
|
2016-09-10 07:00:50 +00:00
|
|
|
template <return_value_policy Policy = return_value_policy::reference_internal,
|
|
|
|
typename Type, typename... Extra> iterator make_iterator(Type &value, Extra&&... extra) {
|
|
|
|
return make_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
2016-04-18 08:52:12 +00:00
|
|
|
}
|
|
|
|
|
2016-09-10 07:00:50 +00:00
|
|
|
template <return_value_policy Policy = return_value_policy::reference_internal,
|
|
|
|
typename Type, typename... Extra> iterator make_key_iterator(Type &value, Extra&&... extra) {
|
|
|
|
return make_key_iterator<Policy>(std::begin(value), std::end(value), extra...);
|
2016-08-12 01:22:05 +00:00
|
|
|
}
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
template <typename InputType, typename OutputType> void implicitly_convertible() {
|
moved processing of cpp_function arguments out of dispatch code
The cpp_function class accepts a variadic argument, which was formerly
processed twice -- once at registration time, and once in the dispatch
lambda function. This is not only unnecessarily slow but also leads to
code bloat since it adds to the object code generated for every bound
function. This change removes the second pass at dispatch time.
One noteworthy change of this commit is that default arguments are now
constructed (and converted to Python objects) right at declaration time.
Consider the following example:
py::class_<MyClass>("MyClass")
.def("myFunction", py::arg("arg") = SomeType(123));
In this case, the change means that pybind11 must already be set up to
deal with values of the type 'SomeType', or an exception will be thrown.
Another change is that the "preview" of the default argument in the
function signature is generated using the __repr__ special method. If
it is not available in this type, the signature may not be very helpful,
i.e.:
| myFunction(...)
| Signature : (MyClass, arg : SomeType = <SomeType object at 0x101b7b080>) -> None
One workaround (other than defining SomeType.__repr__) is to specify the
human-readable preview of the default argument manually using the more
cumbersome arg_t notation:
py::class_<MyClass>("MyClass")
.def("myFunction", py::arg_t<SomeType>("arg", SomeType(123), "SomeType(123)"));
2016-01-17 21:36:35 +00:00
|
|
|
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
|
2015-07-05 18:05:44 +00:00
|
|
|
if (!detail::type_caster<InputType>().load(obj, false))
|
|
|
|
return nullptr;
|
|
|
|
tuple args(1);
|
|
|
|
args[0] = obj;
|
|
|
|
PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
|
|
|
|
if (result == nullptr)
|
|
|
|
PyErr_Clear();
|
|
|
|
return result;
|
|
|
|
};
|
2016-10-23 14:43:03 +00:00
|
|
|
|
|
|
|
if (auto tinfo = detail::get_type_info(typeid(OutputType)))
|
|
|
|
tinfo->implicit_conversions.push_back(implicit_caster);
|
|
|
|
else
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("implicitly_convertible: Unable to find type " + type_id<OutputType>());
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 21:35:59 +00:00
|
|
|
template <typename ExceptionTranslator>
|
|
|
|
void register_exception_translator(ExceptionTranslator&& translator) {
|
|
|
|
detail::get_internals().registered_exception_translators.push_front(
|
|
|
|
std::forward<ExceptionTranslator>(translator));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wrapper to generate a new Python exception type.
|
|
|
|
*
|
|
|
|
* This should only be used with PyErr_SetString for now.
|
|
|
|
* It is not (yet) possible to use as a py::base.
|
|
|
|
* Template type argument is reserved for future use.
|
|
|
|
*/
|
|
|
|
template <typename type>
|
|
|
|
class exception : public object {
|
|
|
|
public:
|
2016-11-16 16:59:56 +00:00
|
|
|
exception(handle scope, const char *name, PyObject *base = PyExc_Exception) {
|
|
|
|
std::string full_name = scope.attr("__name__").cast<std::string>() +
|
|
|
|
std::string(".") + name;
|
|
|
|
m_ptr = PyErr_NewException((char *) full_name.c_str(), base, NULL);
|
|
|
|
if (hasattr(scope, name))
|
|
|
|
pybind11_fail("Error during initialization: multiple incompatible "
|
|
|
|
"definitions with name \"" + std::string(name) + "\"");
|
|
|
|
scope.attr(name) = *this;
|
2016-06-17 21:35:59 +00:00
|
|
|
}
|
2016-09-16 06:04:15 +00:00
|
|
|
|
|
|
|
// Sets the current python exception to this exception object with the given message
|
|
|
|
void operator()(const char *message) {
|
|
|
|
PyErr_SetString(m_ptr, message);
|
|
|
|
}
|
2016-06-17 21:35:59 +00:00
|
|
|
};
|
|
|
|
|
2016-09-16 06:04:15 +00:00
|
|
|
/** Registers a Python exception in `m` of the given `name` and installs an exception translator to
|
|
|
|
* translate the C++ exception to the created Python exception using the exceptions what() method.
|
|
|
|
* This is intended for simple exception translations; for more complex translation, register the
|
|
|
|
* exception object and translator directly.
|
|
|
|
*/
|
2016-11-16 16:59:56 +00:00
|
|
|
template <typename CppException>
|
|
|
|
exception<CppException> ®ister_exception(handle scope,
|
|
|
|
const char *name,
|
|
|
|
PyObject *base = PyExc_Exception) {
|
|
|
|
static exception<CppException> ex(scope, name, base);
|
2016-09-16 06:04:15 +00:00
|
|
|
register_exception_translator([](std::exception_ptr p) {
|
|
|
|
if (!p) return;
|
|
|
|
try {
|
|
|
|
std::rethrow_exception(p);
|
2016-11-16 16:59:56 +00:00
|
|
|
} catch (const CppException &e) {
|
2016-09-16 06:04:15 +00:00
|
|
|
ex(e.what());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return ex;
|
|
|
|
}
|
|
|
|
|
2016-08-29 16:03:34 +00:00
|
|
|
NAMESPACE_BEGIN(detail)
|
|
|
|
PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) {
|
|
|
|
auto strings = tuple(args.size());
|
|
|
|
for (size_t i = 0; i < args.size(); ++i) {
|
2016-10-25 20:12:39 +00:00
|
|
|
strings[i] = str(args[i]);
|
2016-08-29 16:03:34 +00:00
|
|
|
}
|
2016-09-20 23:06:32 +00:00
|
|
|
auto sep = kwargs.contains("sep") ? kwargs["sep"] : cast(" ");
|
2016-09-08 15:02:04 +00:00
|
|
|
auto line = sep.attr("join")(strings);
|
2016-08-29 16:03:34 +00:00
|
|
|
|
2016-10-13 08:34:52 +00:00
|
|
|
object file;
|
|
|
|
if (kwargs.contains("file")) {
|
|
|
|
file = kwargs["file"].cast<object>();
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
file = module::import("sys").attr("stdout");
|
|
|
|
} catch (const import_error &) {
|
|
|
|
/* If print() is called from code that is executed as
|
|
|
|
part of garbage collection during interpreter shutdown,
|
|
|
|
importing 'sys' can fail. Give up rather than crashing the
|
|
|
|
interpreter in this case. */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-08 15:02:04 +00:00
|
|
|
auto write = file.attr("write");
|
2016-08-29 16:03:34 +00:00
|
|
|
write(line);
|
2016-09-20 23:06:32 +00:00
|
|
|
write(kwargs.contains("end") ? kwargs["end"] : cast("\n"));
|
2016-08-29 16:03:34 +00:00
|
|
|
|
2016-10-13 08:34:52 +00:00
|
|
|
if (kwargs.contains("flush") && kwargs["flush"].cast<bool>())
|
2016-09-08 15:02:04 +00:00
|
|
|
file.attr("flush")();
|
2016-08-29 16:03:34 +00:00
|
|
|
}
|
|
|
|
NAMESPACE_END(detail)
|
|
|
|
|
|
|
|
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
|
|
|
|
void print(Args &&...args) {
|
|
|
|
auto c = detail::collect_arguments<policy>(std::forward<Args>(args)...);
|
|
|
|
detail::print(c.args(), c.kwargs());
|
|
|
|
}
|
|
|
|
|
2016-01-25 19:22:44 +00:00
|
|
|
#if defined(WITH_THREAD)
|
2016-04-25 01:26:15 +00:00
|
|
|
|
|
|
|
/* The functions below essentially reproduce the PyGILState_* API using a RAII
|
|
|
|
* pattern, but there are a few important differences:
|
|
|
|
*
|
|
|
|
* 1. When acquiring the GIL from an non-main thread during the finalization
|
|
|
|
* phase, the GILState API blindly terminates the calling thread, which
|
|
|
|
* is often not what is wanted. This API does not do this.
|
|
|
|
*
|
|
|
|
* 2. The gil_scoped_release function can optionally cut the relationship
|
|
|
|
* of a PyThreadState and its associated thread, which allows moving it to
|
|
|
|
* another thread (this is a fairly rare/advanced use case).
|
|
|
|
*
|
|
|
|
* 3. The reference count of an acquired thread state can be controlled. This
|
|
|
|
* can be handy to prevent cases where callbacks issued from an external
|
2016-04-25 13:02:43 +00:00
|
|
|
* thread would otherwise constantly construct and destroy thread state data
|
|
|
|
* structures.
|
2016-05-26 12:29:31 +00:00
|
|
|
*
|
|
|
|
* See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an
|
|
|
|
* example which uses features 2 and 3 to migrate the Python thread of
|
|
|
|
* execution to another thread (to run the event loop on the original thread,
|
|
|
|
* in this case).
|
2016-04-25 13:02:43 +00:00
|
|
|
*/
|
2015-07-05 18:05:44 +00:00
|
|
|
|
|
|
|
class gil_scoped_acquire {
|
|
|
|
public:
|
2016-04-25 13:02:43 +00:00
|
|
|
PYBIND11_NOINLINE gil_scoped_acquire() {
|
2016-04-25 01:26:15 +00:00
|
|
|
auto const &internals = detail::get_internals();
|
|
|
|
tstate = (PyThreadState *) PyThread_get_key_value(internals.tstate);
|
|
|
|
|
|
|
|
if (!tstate) {
|
|
|
|
tstate = PyThreadState_New(internals.istate);
|
|
|
|
#if !defined(NDEBUG)
|
|
|
|
if (!tstate)
|
|
|
|
pybind11_fail("scoped_acquire: could not create thread state!");
|
|
|
|
#endif
|
|
|
|
tstate->gilstate_counter = 0;
|
2016-04-25 13:02:43 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
PyThread_delete_key_value(internals.tstate);
|
|
|
|
#endif
|
2016-04-25 01:26:15 +00:00
|
|
|
PyThread_set_key_value(internals.tstate, tstate);
|
|
|
|
} else {
|
2016-04-25 13:02:43 +00:00
|
|
|
release = detail::get_thread_state_unchecked() != tstate;
|
2016-04-25 01:26:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (release) {
|
|
|
|
/* Work around an annoying assertion in PyThreadState_Swap */
|
2016-04-25 13:02:43 +00:00
|
|
|
#if defined(Py_DEBUG)
|
|
|
|
PyInterpreterState *interp = tstate->interp;
|
|
|
|
tstate->interp = nullptr;
|
|
|
|
#endif
|
2016-04-25 01:26:15 +00:00
|
|
|
PyEval_AcquireThread(tstate);
|
2016-04-25 13:02:43 +00:00
|
|
|
#if defined(Py_DEBUG)
|
|
|
|
tstate->interp = interp;
|
|
|
|
#endif
|
2016-04-25 01:26:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inc_ref();
|
|
|
|
}
|
|
|
|
|
|
|
|
void inc_ref() {
|
|
|
|
++tstate->gilstate_counter;
|
|
|
|
}
|
|
|
|
|
2016-04-25 13:02:43 +00:00
|
|
|
PYBIND11_NOINLINE void dec_ref() {
|
2016-04-25 01:26:15 +00:00
|
|
|
--tstate->gilstate_counter;
|
|
|
|
#if !defined(NDEBUG)
|
2016-04-25 13:02:43 +00:00
|
|
|
if (detail::get_thread_state_unchecked() != tstate)
|
2016-04-25 01:26:15 +00:00
|
|
|
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
|
|
|
|
if (tstate->gilstate_counter < 0)
|
|
|
|
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
|
|
|
|
#endif
|
|
|
|
if (tstate->gilstate_counter == 0) {
|
|
|
|
#if !defined(NDEBUG)
|
|
|
|
if (!release)
|
|
|
|
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
|
|
|
|
#endif
|
|
|
|
PyThreadState_Clear(tstate);
|
|
|
|
PyThreadState_DeleteCurrent();
|
2016-04-25 13:02:43 +00:00
|
|
|
PyThread_delete_key_value(detail::get_internals().tstate);
|
2016-04-25 01:26:15 +00:00
|
|
|
release = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-25 13:02:43 +00:00
|
|
|
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
2016-04-25 01:26:15 +00:00
|
|
|
dec_ref();
|
|
|
|
if (release)
|
|
|
|
PyEval_SaveThread();
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
PyThreadState *tstate = nullptr;
|
|
|
|
bool release = true;
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class gil_scoped_release {
|
|
|
|
public:
|
2016-10-16 20:27:42 +00:00
|
|
|
explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
|
2016-04-25 01:26:15 +00:00
|
|
|
tstate = PyEval_SaveThread();
|
2016-04-25 07:16:41 +00:00
|
|
|
if (disassoc) {
|
2016-05-28 10:26:18 +00:00
|
|
|
auto key = detail::get_internals().tstate;
|
2016-04-25 07:16:41 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
PyThread_delete_key_value(key);
|
|
|
|
#else
|
|
|
|
PyThread_set_key_value(key, nullptr);
|
|
|
|
#endif
|
|
|
|
}
|
2016-04-25 01:26:15 +00:00
|
|
|
}
|
|
|
|
~gil_scoped_release() {
|
|
|
|
if (!tstate)
|
|
|
|
return;
|
|
|
|
PyEval_RestoreThread(tstate);
|
2016-04-25 07:16:41 +00:00
|
|
|
if (disassoc) {
|
2016-05-28 10:26:18 +00:00
|
|
|
auto key = detail::get_internals().tstate;
|
2016-04-25 07:16:41 +00:00
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
|
|
PyThread_delete_key_value(key);
|
|
|
|
#endif
|
|
|
|
PyThread_set_key_value(key, tstate);
|
|
|
|
}
|
2016-04-25 01:26:15 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
PyThreadState *tstate;
|
|
|
|
bool disassoc;
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
2016-04-25 01:26:15 +00:00
|
|
|
#else
|
|
|
|
class gil_scoped_acquire { };
|
|
|
|
class gil_scoped_release { };
|
2016-01-25 19:22:44 +00:00
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-08-09 21:57:59 +00:00
|
|
|
inline function get_type_overload(const void *this_ptr, const detail::type_info *this_type, const char *name) {
|
|
|
|
handle py_object = detail::get_object_handle(this_ptr, this_type);
|
2015-10-01 16:37:26 +00:00
|
|
|
if (!py_object)
|
|
|
|
return function();
|
2015-10-01 14:46:03 +00:00
|
|
|
handle type = py_object.get_type();
|
|
|
|
auto key = std::make_pair(type.ptr(), name);
|
|
|
|
|
2016-04-11 16:13:08 +00:00
|
|
|
/* Cache functions that aren't overloaded in Python to avoid
|
|
|
|
many costly Python dictionary lookups below */
|
2015-10-01 14:46:03 +00:00
|
|
|
auto &cache = detail::get_internals().inactive_overload_cache;
|
|
|
|
if (cache.find(key) != cache.end())
|
|
|
|
return function();
|
|
|
|
|
2016-09-20 23:06:32 +00:00
|
|
|
function overload = getattr(py_object, name, function());
|
2015-10-01 14:46:03 +00:00
|
|
|
if (overload.is_cpp_function()) {
|
|
|
|
cache.insert(key);
|
|
|
|
return function();
|
|
|
|
}
|
2016-01-17 21:36:37 +00:00
|
|
|
|
2016-04-11 16:13:08 +00:00
|
|
|
/* Don't call dispatch code if invoked from overridden function */
|
2015-10-01 14:46:03 +00:00
|
|
|
PyFrameObject *frame = PyThreadState_Get()->frame;
|
2016-10-25 20:12:39 +00:00
|
|
|
if (frame && (std::string) str(frame->f_code->co_name) == name &&
|
2016-04-11 16:13:08 +00:00
|
|
|
frame->f_code->co_argcount > 0) {
|
|
|
|
PyFrame_FastToLocals(frame);
|
|
|
|
PyObject *self_caller = PyDict_GetItem(
|
|
|
|
frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));
|
|
|
|
if (self_caller == py_object.ptr())
|
|
|
|
return function();
|
|
|
|
}
|
2015-10-01 14:46:03 +00:00
|
|
|
return overload;
|
|
|
|
}
|
|
|
|
|
2016-08-09 21:57:59 +00:00
|
|
|
template <class T> function get_overload(const T *this_ptr, const char *name) {
|
2016-10-23 14:43:03 +00:00
|
|
|
auto tinfo = detail::get_type_info(typeid(T));
|
|
|
|
return tinfo ? get_type_overload(this_ptr, tinfo, name) : function();
|
2016-08-09 21:57:59 +00:00
|
|
|
}
|
|
|
|
|
Fix template trampoline overload lookup failure
Problem
=======
The template trampoline pattern documented in PR #322 has a problem with
virtual method overloads in intermediate classes in the inheritance
chain between the trampoline class and the base class.
For example, consider the following inheritance structure, where `B` is
the actual class, `PyB<B>` is the trampoline class, and `PyA<B>` is an
intermediate class adding A's methods into the trampoline:
PyB<B> -> PyA<B> -> B -> A
Suppose PyA<B> has a method `some_method()` with a PYBIND11_OVERLOAD in
it to overload the virtual `A::some_method()`. If a Python class `C` is
defined that inherits from the pybind11-registered `B` and tries to
provide an overriding `some_method()`, the PYBIND11_OVERLOADs declared
in PyA<B> fails to find this overloaded method, and thus never invoke it
(or, if pure virtual and not overridden in PyB<B>, raises an exception).
This happens because the base (internal) `PYBIND11_OVERLOAD_INT` macro
simply calls `get_overload(this, name)`; `get_overload()` then uses the
inferred type of `this` to do a type lookup in `registered_types_cpp`.
This is where it fails: `this` will be a `PyA<B> *`, but `PyA<B>` is
neither the base type (`B`) nor the trampoline type (`PyB<B>`). As a
result, the overload fails and we get a failed overload lookup.
The fix
=======
The fix is relatively simple: we can cast `this` passed to
`get_overload()` to a `const B *`, which lets get_overload look up the
correct class. Since trampoline classes should be derived from `B`
classes anyway, this cast should be perfectly safe.
This does require adding the class name as an argument to the
PYBIND11_OVERLOAD_INT macro, but leaves the public macro signatures
unchanged.
2016-08-29 22:16:46 +00:00
|
|
|
#define PYBIND11_OVERLOAD_INT(ret_type, cname, name, ...) { \
|
2015-10-15 16:13:33 +00:00
|
|
|
pybind11::gil_scoped_acquire gil; \
|
Fix template trampoline overload lookup failure
Problem
=======
The template trampoline pattern documented in PR #322 has a problem with
virtual method overloads in intermediate classes in the inheritance
chain between the trampoline class and the base class.
For example, consider the following inheritance structure, where `B` is
the actual class, `PyB<B>` is the trampoline class, and `PyA<B>` is an
intermediate class adding A's methods into the trampoline:
PyB<B> -> PyA<B> -> B -> A
Suppose PyA<B> has a method `some_method()` with a PYBIND11_OVERLOAD in
it to overload the virtual `A::some_method()`. If a Python class `C` is
defined that inherits from the pybind11-registered `B` and tries to
provide an overriding `some_method()`, the PYBIND11_OVERLOADs declared
in PyA<B> fails to find this overloaded method, and thus never invoke it
(or, if pure virtual and not overridden in PyB<B>, raises an exception).
This happens because the base (internal) `PYBIND11_OVERLOAD_INT` macro
simply calls `get_overload(this, name)`; `get_overload()` then uses the
inferred type of `this` to do a type lookup in `registered_types_cpp`.
This is where it fails: `this` will be a `PyA<B> *`, but `PyA<B>` is
neither the base type (`B`) nor the trampoline type (`PyB<B>`). As a
result, the overload fails and we get a failed overload lookup.
The fix
=======
The fix is relatively simple: we can cast `this` passed to
`get_overload()` to a `const B *`, which lets get_overload look up the
correct class. Since trampoline classes should be derived from `B`
classes anyway, this cast should be perfectly safe.
This does require adding the class name as an argument to the
PYBIND11_OVERLOAD_INT macro, but leaves the public macro signatures
unchanged.
2016-08-29 22:16:46 +00:00
|
|
|
pybind11::function overload = pybind11::get_overload(static_cast<const cname *>(this), name); \
|
2016-09-08 18:49:43 +00:00
|
|
|
if (overload) { \
|
2016-09-11 16:17:41 +00:00
|
|
|
auto o = overload(__VA_ARGS__); \
|
2016-09-08 18:49:43 +00:00
|
|
|
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) { \
|
2016-09-11 16:17:41 +00:00
|
|
|
static pybind11::detail::overload_caster_t<ret_type> caster; \
|
|
|
|
return pybind11::detail::cast_ref<ret_type>(std::move(o), caster); \
|
2016-09-08 18:49:43 +00:00
|
|
|
} \
|
|
|
|
else return pybind11::detail::cast_safe<ret_type>(std::move(o)); \
|
|
|
|
} \
|
|
|
|
}
|
2015-10-01 14:46:03 +00:00
|
|
|
|
2016-05-24 21:42:05 +00:00
|
|
|
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
|
Fix template trampoline overload lookup failure
Problem
=======
The template trampoline pattern documented in PR #322 has a problem with
virtual method overloads in intermediate classes in the inheritance
chain between the trampoline class and the base class.
For example, consider the following inheritance structure, where `B` is
the actual class, `PyB<B>` is the trampoline class, and `PyA<B>` is an
intermediate class adding A's methods into the trampoline:
PyB<B> -> PyA<B> -> B -> A
Suppose PyA<B> has a method `some_method()` with a PYBIND11_OVERLOAD in
it to overload the virtual `A::some_method()`. If a Python class `C` is
defined that inherits from the pybind11-registered `B` and tries to
provide an overriding `some_method()`, the PYBIND11_OVERLOADs declared
in PyA<B> fails to find this overloaded method, and thus never invoke it
(or, if pure virtual and not overridden in PyB<B>, raises an exception).
This happens because the base (internal) `PYBIND11_OVERLOAD_INT` macro
simply calls `get_overload(this, name)`; `get_overload()` then uses the
inferred type of `this` to do a type lookup in `registered_types_cpp`.
This is where it fails: `this` will be a `PyA<B> *`, but `PyA<B>` is
neither the base type (`B`) nor the trampoline type (`PyB<B>`). As a
result, the overload fails and we get a failed overload lookup.
The fix
=======
The fix is relatively simple: we can cast `this` passed to
`get_overload()` to a `const B *`, which lets get_overload look up the
correct class. Since trampoline classes should be derived from `B`
classes anyway, this cast should be perfectly safe.
This does require adding the class name as an argument to the
PYBIND11_OVERLOAD_INT macro, but leaves the public macro signatures
unchanged.
2016-08-29 22:16:46 +00:00
|
|
|
PYBIND11_OVERLOAD_INT(ret_type, cname, name, __VA_ARGS__) \
|
2016-05-24 21:42:05 +00:00
|
|
|
return cname::fn(__VA_ARGS__)
|
2015-10-01 14:46:03 +00:00
|
|
|
|
2016-05-24 21:42:05 +00:00
|
|
|
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
|
Fix template trampoline overload lookup failure
Problem
=======
The template trampoline pattern documented in PR #322 has a problem with
virtual method overloads in intermediate classes in the inheritance
chain between the trampoline class and the base class.
For example, consider the following inheritance structure, where `B` is
the actual class, `PyB<B>` is the trampoline class, and `PyA<B>` is an
intermediate class adding A's methods into the trampoline:
PyB<B> -> PyA<B> -> B -> A
Suppose PyA<B> has a method `some_method()` with a PYBIND11_OVERLOAD in
it to overload the virtual `A::some_method()`. If a Python class `C` is
defined that inherits from the pybind11-registered `B` and tries to
provide an overriding `some_method()`, the PYBIND11_OVERLOADs declared
in PyA<B> fails to find this overloaded method, and thus never invoke it
(or, if pure virtual and not overridden in PyB<B>, raises an exception).
This happens because the base (internal) `PYBIND11_OVERLOAD_INT` macro
simply calls `get_overload(this, name)`; `get_overload()` then uses the
inferred type of `this` to do a type lookup in `registered_types_cpp`.
This is where it fails: `this` will be a `PyA<B> *`, but `PyA<B>` is
neither the base type (`B`) nor the trampoline type (`PyB<B>`). As a
result, the overload fails and we get a failed overload lookup.
The fix
=======
The fix is relatively simple: we can cast `this` passed to
`get_overload()` to a `const B *`, which lets get_overload look up the
correct class. Since trampoline classes should be derived from `B`
classes anyway, this cast should be perfectly safe.
This does require adding the class name as an argument to the
PYBIND11_OVERLOAD_INT macro, but leaves the public macro signatures
unchanged.
2016-08-29 22:16:46 +00:00
|
|
|
PYBIND11_OVERLOAD_INT(ret_type, cname, name, __VA_ARGS__) \
|
2016-05-24 21:42:05 +00:00
|
|
|
pybind11::pybind11_fail("Tried to call pure virtual function \"" #cname "::" name "\"");
|
|
|
|
|
|
|
|
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
|
|
|
|
PYBIND11_OVERLOAD_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
|
|
|
|
PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, #fn, fn, __VA_ARGS__)
|
2015-10-01 14:46:03 +00:00
|
|
|
|
2015-10-15 16:13:33 +00:00
|
|
|
NAMESPACE_END(pybind11)
|
2015-07-05 18:05:44 +00:00
|
|
|
|
|
|
|
#if defined(_MSC_VER)
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma warning(pop)
|
2016-08-24 23:43:33 +00:00
|
|
|
#elif defined(__INTEL_COMPILER)
|
|
|
|
/* Leave ignored warnings on */
|
2016-05-01 18:47:49 +00:00
|
|
|
#elif defined(__GNUG__) && !defined(__clang__)
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma GCC diagnostic pop
|
2015-07-05 18:05:44 +00:00
|
|
|
#endif
|