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
|
|
|
|
|
|
|
Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
|
|
|
|
|
|
|
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)
|
|
|
|
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
|
|
|
# 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
|
|
|
|
# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
|
|
|
|
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
|
2016-02-18 18:06:43 +00:00
|
|
|
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
2016-02-18 20:25:51 +00:00
|
|
|
# pragma warning(push)
|
2016-02-18 18:06:43 +00:00
|
|
|
# pragma warning(disable:2196) // warning #2196: routine is both "inline" and "noinline"
|
2015-08-03 10:17:54 +00:00
|
|
|
#elif defined(__GNUG__) and !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"
|
2015-07-05 18:05:44 +00:00
|
|
|
#endif
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
#include "attr.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 {
|
2016-01-17 21:36:41 +00:00
|
|
|
protected:
|
2015-07-26 14:33:49 +00:00
|
|
|
/// Picks a suitable return value converter from cast.h
|
|
|
|
template <typename T> using return_value_caster =
|
|
|
|
detail::type_caster<typename std::conditional<
|
2016-01-17 21:36:38 +00:00
|
|
|
std::is_void<T>::value, detail::void_type, typename detail::intrinsic_type<T>::type>::type>;
|
2015-07-26 14:33:49 +00:00
|
|
|
|
|
|
|
/// Picks a suitable argument value converter from cast.h
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename... T> using arg_value_caster =
|
2015-07-26 14:33:49 +00:00
|
|
|
detail::type_caster<typename std::tuple<T...>>;
|
|
|
|
public:
|
2015-07-11 15:41:48 +00:00
|
|
|
cpp_function() { }
|
2015-07-26 14:33:49 +00:00
|
|
|
|
|
|
|
/// Vanilla function pointers
|
2016-01-17 21:36:36 +00:00
|
|
|
template <typename Return, typename... Args, typename... Extra>
|
2016-01-17 21:36:44 +00:00
|
|
|
cpp_function(Return (*f)(Args...), const Extra&... extra) {
|
|
|
|
auto rec = new detail::function_record();
|
|
|
|
rec->data = (void *) f;
|
2015-07-26 14:33:49 +00:00
|
|
|
|
2016-01-17 21:36:36 +00:00
|
|
|
typedef arg_value_caster<Args...> cast_in;
|
2015-07-29 15:43:52 +00:00
|
|
|
typedef return_value_caster<Return> cast_out;
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Dispatch code which converts function arguments and performs the actual function call */
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->impl = [](detail::function_record *rec, handle pyArgs, handle parent) -> handle {
|
2015-07-05 18:05:44 +00:00
|
|
|
cast_in args;
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Try to cast the function arguments into the C++ domain */
|
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
|
|
|
if (!args.load(pyArgs, 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 */
|
|
|
|
detail::process_attributes<Extra...>::precall(pyArgs);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Do the call and convert the return value back into the Python domain */
|
2016-01-17 21:36:44 +00:00
|
|
|
handle result = cast_out::cast(
|
|
|
|
args.template call<Return>((Return (*) (Args...)) rec->data),
|
|
|
|
rec->policy, parent);
|
|
|
|
|
|
|
|
/* Invoke call policy post-call hook */
|
|
|
|
detail::process_attributes<Extra...>::postcall(pyArgs, result);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-01-17 21:36:39 +00:00
|
|
|
return result;
|
2015-07-05 18:05:44 +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-01-17 21:36:44 +00:00
|
|
|
using detail::descr;
|
2016-03-08 23:44:04 +00:00
|
|
|
PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name();
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Register the function with Python from generic (non-templated) code */
|
2016-01-17 21:36:44 +00:00
|
|
|
initialize(rec, signature.text(), signature.types(), sizeof...(Args));
|
2015-07-26 14:33:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Delegating helper constructor to deal with lambda functions
|
2016-01-17 21:36:44 +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-01-17 21:36:41 +00:00
|
|
|
/// Delegating helper constructor to deal with class methods (non-const)
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
|
2016-01-17 21:36:44 +00:00
|
|
|
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-01-17 21:36:41 +00:00
|
|
|
/// Delegating helper constructor to deal with class methods (const)
|
2015-07-29 15:43:52 +00:00
|
|
|
template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
|
2016-01-17 21:36:44 +00:00
|
|
|
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:
|
|
|
|
/// 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-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-01-17 21:36:44 +00:00
|
|
|
auto rec = new detail::function_record();
|
|
|
|
rec->data = new capture { std::forward<Func>(f) };
|
2015-07-29 15:43:52 +00:00
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Create a cleanup handler, but only if we have to (less generated code) */
|
2015-10-13 15:37:25 +00:00
|
|
|
if (!std::is_trivially_destructible<Func>::value)
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->free_data = [](void *ptr) { delete (capture *) ptr; };
|
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
|
|
|
else
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->free_data = operator delete;
|
2015-10-13 15:37:25 +00:00
|
|
|
|
2016-01-17 21:36:36 +00:00
|
|
|
typedef arg_value_caster<Args...> cast_in;
|
2015-07-29 15:43:52 +00:00
|
|
|
typedef return_value_caster<Return> 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-01-17 21:36:44 +00:00
|
|
|
rec->impl = [](detail::function_record *rec, handle pyArgs, handle parent) -> handle {
|
2015-07-26 14:33:49 +00:00
|
|
|
cast_in args;
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Try to cast the function arguments into the C++ domain */
|
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
|
|
|
if (!args.load(pyArgs, 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 */
|
|
|
|
detail::process_attributes<Extra...>::precall(pyArgs);
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Do the call and convert the return value back into the Python domain */
|
2016-01-17 21:36:44 +00:00
|
|
|
handle result = cast_out::cast(
|
|
|
|
args.template call<Return>(((capture *) rec->data)->f),
|
|
|
|
rec->policy, parent);
|
|
|
|
|
|
|
|
/* Invoke call policy post-call hook */
|
|
|
|
detail::process_attributes<Extra...>::postcall(pyArgs, 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-01-17 21:36:44 +00:00
|
|
|
using detail::descr;
|
2016-03-08 23:44:04 +00:00
|
|
|
PYBIND11_DESCR signature = cast_in::name() + detail::_(" -> ") + cast_out::name();
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Register the function with Python from generic (non-templated) code */
|
2016-01-17 21:36:44 +00:00
|
|
|
initialize(rec, signature.text(), signature.types(), sizeof...(Args));
|
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-01-17 21:36:44 +00:00
|
|
|
void initialize(detail::function_record *rec, const char *text,
|
|
|
|
const std::type_info *const *types, int args) {
|
|
|
|
|
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-01-17 21:36:37 +00:00
|
|
|
a.descr = strdup(((std::string) ((object) handle(a.value).attr("__repr__")).call().str()).c_str());
|
2016-01-17 21:36:36 +00:00
|
|
|
}
|
2016-01-17 21:36:41 +00:00
|
|
|
auto const ®istered_types = detail::get_internals().registered_types_cpp;
|
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-01-17 21:36:44 +00:00
|
|
|
if (type_depth == 1 && arg_index < rec->args.size()) {
|
|
|
|
signature += rec->args[arg_index].name;
|
2016-01-17 21:36:36 +00:00
|
|
|
signature += " : ";
|
|
|
|
}
|
|
|
|
++type_depth;
|
|
|
|
} else if (c == '}') {
|
|
|
|
--type_depth;
|
2016-01-17 21:36:44 +00:00
|
|
|
if (type_depth == 1 && arg_index < rec->args.size()) {
|
|
|
|
if (rec->args[arg_index].descr) {
|
2016-01-17 21:36:36 +00:00
|
|
|
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-01-29 10:39:32 +00:00
|
|
|
auto it = registered_types.find(std::type_index(*t));
|
2016-01-17 21:36:36 +00:00
|
|
|
if (it != registered_types.end()) {
|
2016-01-17 21:36:41 +00:00
|
|
|
signature += ((const detail::type_info *) it->second)->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-01-17 21:36:36 +00:00
|
|
|
}
|
2015-09-04 21:42:12 +00:00
|
|
|
#endif
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
if (!rec->args.empty() && (int) rec->args.size() != args)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail(
|
2016-01-17 21:36:44 +00:00
|
|
|
"cpp_function(): function \"" + std::string(rec->name) + "\" takes " +
|
|
|
|
std::to_string(args) + " arguments, but " + std::to_string(rec->args.size()) +
|
2015-10-15 16:13:33 +00:00
|
|
|
" pybind11::arg entries were specified!");
|
2015-07-11 15:41:48 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
rec->is_constructor = !strcmp(rec->name, "__init__");
|
|
|
|
rec->signature = strdup(signature.c_str());
|
|
|
|
rec->args.shrink_to_fit();
|
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;
|
|
|
|
if (rec->sibling && PyCFunction_Check(rec->sibling.ptr())) {
|
|
|
|
capsule rec_capsule(PyCFunction_GetSelf(rec->sibling.ptr()), true);
|
|
|
|
chain = (detail::function_record *) rec_capsule;
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Never append a method to an overload chain of a parent class;
|
|
|
|
instead, hide the parent's overloads in this case */
|
2016-01-17 21:36:44 +00:00
|
|
|
if (chain->class_ != rec->class_)
|
|
|
|
chain = nullptr;
|
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) {
|
|
|
|
scope_module = (object) rec->scope.attr("__module__");
|
|
|
|
if (!scope_module)
|
|
|
|
scope_module = (object) rec->scope.attr("__name__");
|
|
|
|
}
|
|
|
|
|
|
|
|
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-03-08 21:42:12 +00:00
|
|
|
if (chain) {
|
|
|
|
// 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) {
|
|
|
|
if (chain)
|
2015-07-29 15:43:52 +00:00
|
|
|
signatures += std::to_string(++index) + ". ";
|
2016-02-29 02:23:39 +00:00
|
|
|
signatures += rec->name;
|
2016-01-17 21:36:36 +00:00
|
|
|
signatures += it->signature;
|
|
|
|
signatures += "\n";
|
|
|
|
if (it->doc && strlen(it->doc) > 0) {
|
|
|
|
signatures += "\n";
|
2016-02-28 22:52:37 +00:00
|
|
|
signatures += it->doc;
|
2016-01-17 21:36:36 +00:00
|
|
|
signatures += "\n";
|
|
|
|
}
|
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)
|
|
|
|
rec->free_data(rec->data);
|
|
|
|
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 */
|
|
|
|
int nargs = (int) PyTuple_Size(args),
|
|
|
|
nkwargs = kwargs ? (int) PyDict_Size(kwargs) : 0;
|
|
|
|
|
|
|
|
handle parent = nargs > 0 ? PyTuple_GetItem(args, 0) : nullptr,
|
|
|
|
result = PYBIND11_TRY_NEXT_OVERLOAD;
|
|
|
|
try {
|
|
|
|
for (; it != nullptr; it = it->next) {
|
|
|
|
tuple args_(args, true);
|
|
|
|
int kwargs_consumed = 0;
|
|
|
|
|
|
|
|
/* 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)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (nargs < (int) it->args.size()) {
|
|
|
|
args_ = tuple(it->args.size());
|
|
|
|
for (int i = 0; i < nargs; ++i) {
|
|
|
|
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 {
|
|
|
|
kwargs_consumed = -1; /* definite failure */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kwargs_consumed == nkwargs)
|
|
|
|
result = it->impl(it, args_, parent);
|
|
|
|
|
|
|
|
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (const error_already_set &) { return nullptr;
|
|
|
|
} catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
|
|
|
|
} catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
|
|
|
|
} catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return nullptr;
|
|
|
|
} catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
|
|
|
|
} catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
|
|
|
|
} catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
|
|
|
|
} catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
|
|
|
|
} catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return nullptr;
|
|
|
|
} catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return nullptr;
|
|
|
|
} catch (...) {
|
|
|
|
PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) {
|
|
|
|
std::string msg = "Incompatible function arguments. The "
|
|
|
|
"following argument types are supported:\n";
|
|
|
|
int ctr = 0;
|
|
|
|
for (detail::function_record *it2 = overloads; it2 != nullptr; it2 = it2->next) {
|
|
|
|
msg += " "+ std::to_string(++ctr) + ". ";
|
|
|
|
msg += it2->signature;
|
|
|
|
msg += "\n";
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
/* When a construtor ran successfully, the corresponding
|
|
|
|
holder type (e.g. std::unique_ptr) must still be initialized. */
|
|
|
|
PyObject *inst = PyTuple_GetItem(args, 0);
|
|
|
|
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
|
|
|
|
|
|
|
module(const char *name, const char *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) {
|
2015-07-29 15:43:52 +00:00
|
|
|
cpp_function func(std::forward<Func>(f), name(name_),
|
2016-02-04 22:02:07 +00:00
|
|
|
sibling((handle) attr(name_)), scope(*this), extra...);
|
2016-01-17 21:36:44 +00:00
|
|
|
/* PyModule_AddObject steals a reference to 'func' */
|
|
|
|
PyModule_AddObject(ptr(), name_, func.inc_ref().ptr());
|
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);
|
|
|
|
module result(PyImport_AddModule(full_name.c_str()), true);
|
2015-07-11 15:41:48 +00:00
|
|
|
if (doc)
|
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-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("Module \"" + std::string(name) + "\" not found!");
|
2015-12-26 13:04:52 +00:00
|
|
|
return module(obj, false);
|
2015-10-13 21:44:25 +00:00
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
NAMESPACE_BEGIN(detail)
|
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 {
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename type, typename holder_type> 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) {
|
|
|
|
if (rec->base_type) {
|
|
|
|
if (rec->base_handle)
|
|
|
|
pybind11_fail("generic_type: specified base type multiple times!");
|
|
|
|
rec->base_handle = detail::get_type_handle(*(rec->base_type));
|
|
|
|
if (!rec->base_handle) {
|
|
|
|
std::string tname(rec->base_type->name());
|
|
|
|
detail::clean_type_id(tname);
|
|
|
|
pybind11_fail("generic_type: type \"" + std::string(rec->name) +
|
|
|
|
"\" referenced unknown base type \"" + tname + "\"");
|
|
|
|
}
|
|
|
|
}
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
2016-01-17 21:36:44 +00:00
|
|
|
object name(PYBIND11_FROM_STRING(rec->name), false);
|
2016-01-17 21:36:41 +00:00
|
|
|
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
|
|
|
|
|
|
|
if (!type_holder || !name)
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("generic_type: unable to create type object!");
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
/* Register supplemental type information in C++ dict */
|
|
|
|
auto &internals = get_internals();
|
|
|
|
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-01-29 10:39:32 +00:00
|
|
|
internals.registered_types_cpp[std::type_index(*(rec->type))] = tinfo;
|
2016-01-17 21:36:41 +00:00
|
|
|
internals.registered_types_py[type] = tinfo;
|
|
|
|
|
2016-04-13 21:33:00 +00:00
|
|
|
object scope_module;
|
|
|
|
if (rec->scope) {
|
|
|
|
scope_module = (object) rec->scope.attr("__module__");
|
|
|
|
if (!scope_module)
|
|
|
|
scope_module = (object) rec->scope.attr("__name__");
|
|
|
|
}
|
2016-01-17 21:36:41 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
std::string full_name = (scope_module ? ((std::string) scope_module.str() + "." + rec->name)
|
|
|
|
: std::string(rec->name));
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Basic type attributes */
|
|
|
|
type->ht_type.tp_name = strdup(full_name.c_str());
|
2016-01-17 21:36:44 +00:00
|
|
|
type->ht_type.tp_basicsize = rec->instance_size;
|
|
|
|
type->ht_type.tp_base = (PyTypeObject *) rec->base_handle.ptr();
|
|
|
|
rec->base_handle.inc_ref();
|
2016-01-17 21:36:41 +00:00
|
|
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
|
|
|
/* Qualified names for Python >= 3.3 */
|
2016-04-13 21:33:00 +00:00
|
|
|
object scope_qualname;
|
|
|
|
if (rec->scope)
|
|
|
|
scope_qualname = (object) rec->scope.attr("__qualname__");
|
2016-01-17 21:36:41 +00:00
|
|
|
if (scope_qualname) {
|
|
|
|
type->ht_qualname = PyUnicode_FromFormat(
|
|
|
|
"%U.%U", scope_qualname.ptr(), name.ptr());
|
|
|
|
} else {
|
|
|
|
type->ht_qualname = name.ptr();
|
|
|
|
name.inc_ref();
|
|
|
|
}
|
2015-09-04 21:42:12 +00:00
|
|
|
#endif
|
2016-01-17 21:36:44 +00:00
|
|
|
type->ht_name = name.release().ptr();
|
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-01-17 21:36:44 +00:00
|
|
|
if (rec->doc) {
|
2016-01-17 21:36:41 +00:00
|
|
|
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
|
|
|
Python will free this later on) */
|
2016-01-17 21:36:44 +00:00
|
|
|
size_t size = strlen(rec->doc) + 1;
|
2016-01-17 21:36:36 +00:00
|
|
|
type->ht_type.tp_doc = (char *) PyObject_MALLOC(size);
|
2016-01-17 21:36:44 +00:00
|
|
|
memcpy((void *) type->ht_type.tp_doc, rec->doc, size);
|
2015-09-05 00:09:17 +00:00
|
|
|
}
|
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: PyType_Ready failed!");
|
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-01-17 21:36:41 +00:00
|
|
|
type_holder.release();
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
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";
|
|
|
|
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
|
|
|
object name(PYBIND11_FROM_STRING(name_.c_str()), false);
|
|
|
|
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();
|
|
|
|
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
|
|
|
/* Qualified names for Python >= 3.3 */
|
|
|
|
type->ht_qualname = PyUnicode_FromFormat(
|
|
|
|
"%U__Meta", ((object) attr("__qualname__")).ptr());
|
|
|
|
#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;
|
|
|
|
self->parent = nullptr;
|
|
|
|
self->constructed = false;
|
|
|
|
detail::get_internals().registered_instances[self->value] = (PyObject *) self;
|
|
|
|
return (PyObject *) self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dealloc(instance<void> *self) {
|
|
|
|
if (self->value) {
|
|
|
|
bool dont_cache = self->parent && ((instance<void> *) self->parent)->value == self->value;
|
|
|
|
if (!dont_cache) { // avoid an issue with internal references matching their parent's address
|
|
|
|
auto ®istered_instances = detail::get_internals().registered_instances;
|
|
|
|
auto it = registered_instances.find(self->value);
|
|
|
|
if (it == registered_instances.end())
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("generic_type::dealloc(): Tried to deallocate unregistered instance!");
|
2015-07-05 18:05:44 +00:00
|
|
|
registered_instances.erase(it);
|
|
|
|
}
|
|
|
|
Py_XDECREF(self->parent);
|
2016-01-17 21:36:39 +00:00
|
|
|
if (self->weakrefs)
|
|
|
|
PyObject_ClearWeakRefs((PyObject *) self);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
Py_TYPE(self)->tp_free((PyObject*) self);
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
view->itemsize = info->itemsize;
|
|
|
|
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) {
|
|
|
|
view->ndim = 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; }
|
|
|
|
};
|
|
|
|
NAMESPACE_END(detail)
|
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename type, typename holder_type = std::unique_ptr<type>>
|
|
|
|
class class_ : public detail::generic_type {
|
2015-07-05 18:05:44 +00:00
|
|
|
public:
|
|
|
|
typedef detail::instance<type, holder_type> instance_type;
|
|
|
|
|
2016-01-17 21:36:41 +00:00
|
|
|
PYBIND11_OBJECT(class_, detail::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);
|
|
|
|
record.type_size = sizeof(type);
|
|
|
|
record.instance_size = sizeof(instance_type);
|
|
|
|
record.init_holder = init_holder;
|
|
|
|
record.dealloc = dealloc;
|
|
|
|
|
|
|
|
/* Process optional arguments, if any */
|
|
|
|
detail::process_attributes<Extra...>::init(extra..., &record);
|
|
|
|
|
|
|
|
detail::generic_type::initialize(&record);
|
|
|
|
}
|
2015-07-05 18:05:44 +00:00
|
|
|
|
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) {
|
2015-09-04 21:42:12 +00:00
|
|
|
cpp_function cf(std::forward<Func>(f), name(name_),
|
2016-01-17 21:36:44 +00:00
|
|
|
sibling(attr(name_)), is_method(*this),
|
|
|
|
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) {
|
2015-09-04 21:42:12 +00:00
|
|
|
cpp_function cf(std::forward<Func>(f), name(name_),
|
2016-02-04 22:02:07 +00:00
|
|
|
sibling(attr(name_)), scope(*this), 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) {
|
2016-02-04 22:29:29 +00:00
|
|
|
op.template execute<type>(*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) {
|
2016-02-04 22:29:29 +00:00
|
|
|
op.template execute_cast<type>(*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) {
|
2016-02-04 22:29:29 +00:00
|
|
|
init.template execute<type>(*this, extra...);
|
2015-07-05 18:05:44 +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-03-21 16:54:24 +00:00
|
|
|
template <typename... Extra>
|
|
|
|
class_ &def_property_readonly(const char *name, const cpp_function &fget, const Extra& ...extra) {
|
|
|
|
def_property(name, fget, cpp_function(), extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
def_property_static(name, fget, cpp_function(), extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
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-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);
|
|
|
|
detail::process_attributes<Extra...>::init(extra..., rec_fget);
|
|
|
|
if (rec_fset)
|
|
|
|
detail::process_attributes<Extra...>::init(extra..., rec_fset);
|
|
|
|
pybind11::str doc_obj = pybind11::str(rec_fget->doc ? rec_fget->doc : "");
|
2015-07-05 18:05:44 +00:00
|
|
|
object property(
|
2016-01-17 21:36:44 +00:00
|
|
|
PyObject_CallFunctionObjArgs((PyObject *) &PyProperty_Type, fget.ptr() ? fget.ptr() : Py_None,
|
|
|
|
fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr), false);
|
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
|
|
|
|
|
|
|
template <typename target> class_ alias() {
|
2016-01-17 21:36:41 +00:00
|
|
|
auto &instances = pybind11::detail::get_internals().registered_types_cpp;
|
2016-01-29 10:39:32 +00:00
|
|
|
instances[std::type_index(typeid(target))] = instances[std::type_index(typeid(type))];
|
2015-10-01 14:46:03 +00:00
|
|
|
return *this;
|
|
|
|
}
|
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-03-08 16:59:10 +00:00
|
|
|
new (&inst->holder) holder_type(std::static_pointer_cast<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);
|
|
|
|
}
|
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,
|
|
|
|
typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer
|
|
|
|
template <typename T = holder_type,
|
|
|
|
typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
|
|
|
|
static void init_holder_helper(instance_type *inst, const holder_type * /* unused */, const void * /* dummy */) {
|
|
|
|
new (&inst->holder) holder_type(inst->value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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
|
|
|
inst->constructed = true;
|
|
|
|
}
|
|
|
|
|
2015-07-05 18:05:44 +00:00
|
|
|
static void dealloc(PyObject *inst_) {
|
|
|
|
instance_type *inst = (instance_type *) inst_;
|
|
|
|
if (inst->owned) {
|
|
|
|
if (inst->constructed)
|
|
|
|
inst->holder.~holder_type();
|
|
|
|
else
|
|
|
|
::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);
|
|
|
|
return h ? (detail::function_record *) capsule(
|
|
|
|
PyCFunction_GetSelf(h.ptr()), true) : nullptr;
|
|
|
|
}
|
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-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) {
|
2015-07-05 18:05:44 +00:00
|
|
|
auto entries = new std::unordered_map<int, const char *>();
|
2015-10-13 00:42:20 +00:00
|
|
|
this->def("__repr__", [name, entries](Type value) -> std::string {
|
2015-08-29 00:08:32 +00:00
|
|
|
auto it = entries->find((int) value);
|
2015-07-05 18:05:44 +00:00
|
|
|
return std::string(name) + "." +
|
|
|
|
((it == entries->end()) ? std::string("???")
|
|
|
|
: std::string(it->second));
|
|
|
|
});
|
2016-01-24 13:05:12 +00:00
|
|
|
this->def("__init__", [](Type& value, int i) { value = (Type) i; });
|
2015-10-01 19:32:23 +00:00
|
|
|
this->def("__int__", [](Type value) { return (int) value; });
|
2016-01-24 13:05:12 +00:00
|
|
|
this->def("__eq__", [](const Type &value, Type value2) { return value == value2; });
|
|
|
|
this->def("__ne__", [](const Type &value, Type value2) { return value != value2; });
|
|
|
|
this->def("__hash__", [](const Type &value) { return (int) value; });
|
2015-07-05 18:05:44 +00:00
|
|
|
m_entries = entries;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Export enumeration entries into the parent scope
|
|
|
|
void export_values() {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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);
|
2015-07-05 18:05:44 +00:00
|
|
|
(*m_entries)[(int) value] = name;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
std::unordered_map<int, 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 {
|
2016-01-17 21:36:44 +00:00
|
|
|
template <typename Base, typename Holder, typename... Extra> void execute(pybind11::class_<Base, Holder> &class_, const Extra&... extra) const {
|
2015-07-05 18:05:44 +00:00
|
|
|
/// Function which calls a specific C++ in-place constructor
|
2016-01-17 21:36:44 +00:00
|
|
|
class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, extra...);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
};
|
2016-01-17 21:36:39 +00:00
|
|
|
|
2016-01-17 21:36:44 +00:00
|
|
|
PYBIND11_NOINLINE inline void keep_alive_impl(int Nurse, int Patient, handle args, handle ret) {
|
2016-01-17 21:36:39 +00:00
|
|
|
/* Clever approach based on weak references taken from Boost.Python */
|
2016-01-17 21:36:44 +00:00
|
|
|
handle nurse (Nurse > 0 ? PyTuple_GetItem(args.ptr(), Nurse - 1) : ret.ptr());
|
|
|
|
handle patient(Patient > 0 ? PyTuple_GetItem(args.ptr(), Patient - 1) : ret.ptr());
|
2016-01-17 21:36:39 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
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-04-13 21:33:00 +00:00
|
|
|
template <typename Iterator> struct iterator_state { Iterator it, end; };
|
|
|
|
|
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...>(); }
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2016-04-13 21:33:00 +00:00
|
|
|
template <typename Iterator, typename... Extra> iterator make_iterator(Iterator first, Iterator last, Extra&&... extra) {
|
|
|
|
typedef detail::iterator_state<Iterator> state;
|
|
|
|
|
|
|
|
if (!detail::get_type_info(typeid(state))) {
|
|
|
|
class_<state>(handle(), "")
|
|
|
|
.def("__iter__", [](state &s) -> state& { return s; })
|
|
|
|
.def("__next__", [](state &s) -> decltype(*std::declval<Iterator>()) & {
|
|
|
|
if (s.it == s.end)
|
|
|
|
throw stop_iteration();
|
|
|
|
return *s.it++;
|
|
|
|
}, return_value_policy::reference_internal, std::forward<Extra>(extra)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (iterator) cast(state { first, last });
|
|
|
|
}
|
|
|
|
|
2016-04-18 08:52:12 +00:00
|
|
|
template <typename Type, typename... Extra> iterator make_iterator(Type &value, Extra&&... extra) {
|
|
|
|
return make_iterator(std::begin(value), std::end(value), extra...);
|
|
|
|
}
|
|
|
|
|
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-01-29 10:39:32 +00:00
|
|
|
auto ®istered_types = detail::get_internals().registered_types_cpp;
|
|
|
|
auto it = registered_types.find(std::type_index(typeid(OutputType)));
|
2015-07-05 18:05:44 +00:00
|
|
|
if (it == registered_types.end())
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11_fail("implicitly_convertible: Unable to find type " + type_id<OutputType>());
|
2016-01-17 21:36:41 +00:00
|
|
|
((detail::type_info *) it->second)->implicit_conversions.push_back(implicit_caster);
|
2015-07-05 18:05:44 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 19:22:44 +00:00
|
|
|
#if defined(WITH_THREAD)
|
2015-07-05 18:05:44 +00:00
|
|
|
inline void init_threading() { PyEval_InitThreads(); }
|
|
|
|
|
|
|
|
class gil_scoped_acquire {
|
|
|
|
PyGILState_STATE state;
|
|
|
|
public:
|
|
|
|
inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
|
|
|
|
inline ~gil_scoped_acquire() { PyGILState_Release(state); }
|
|
|
|
};
|
|
|
|
|
|
|
|
class gil_scoped_release {
|
|
|
|
PyThreadState *state;
|
|
|
|
public:
|
|
|
|
inline gil_scoped_release() { state = PyEval_SaveThread(); }
|
|
|
|
inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
|
|
|
|
};
|
2016-01-25 19:22:44 +00:00
|
|
|
#endif
|
2015-07-05 18:05:44 +00:00
|
|
|
|
2015-10-01 14:46:03 +00:00
|
|
|
inline function get_overload(const void *this_ptr, const char *name) {
|
|
|
|
handle py_object = detail::get_object_handle(this_ptr);
|
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();
|
|
|
|
|
|
|
|
function overload = (function) py_object.attr(name);
|
|
|
|
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-04-15 15:50:40 +00:00
|
|
|
if (frame && (std::string) pybind11::handle(frame->f_code->co_name).str() == 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;
|
|
|
|
}
|
|
|
|
|
2015-10-18 14:48:30 +00:00
|
|
|
#define PYBIND11_OVERLOAD_INT(ret_type, class_name, name, ...) { \
|
2015-10-15 16:13:33 +00:00
|
|
|
pybind11::gil_scoped_acquire gil; \
|
|
|
|
pybind11::function overload = pybind11::get_overload(this, #name); \
|
2015-10-01 14:46:03 +00:00
|
|
|
if (overload) \
|
2016-02-26 12:09:22 +00:00
|
|
|
return overload.call(__VA_ARGS__).template cast<ret_type>(); }
|
2015-10-01 14:46:03 +00:00
|
|
|
|
2015-10-18 14:48:30 +00:00
|
|
|
#define PYBIND11_OVERLOAD(ret_type, class_name, name, ...) \
|
|
|
|
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
|
2015-10-01 14:46:03 +00:00
|
|
|
return class_name::name(__VA_ARGS__)
|
|
|
|
|
2015-10-18 14:48:30 +00:00
|
|
|
#define PYBIND11_OVERLOAD_PURE(ret_type, class_name, name, ...) \
|
|
|
|
PYBIND11_OVERLOAD_INT(ret_type, class_name, name, __VA_ARGS__) \
|
2016-01-17 21:36:41 +00:00
|
|
|
pybind11::pybind11_fail("Tried to call pure virtual function \"" #name "\"");
|
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-02-18 20:25:51 +00:00
|
|
|
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
|
|
|
# pragma warning(pop)
|
2015-08-03 10:17:54 +00:00
|
|
|
#elif defined(__GNUG__) and !defined(__clang__)
|
2016-01-17 21:36:44 +00:00
|
|
|
# pragma GCC diagnostic pop
|
2015-07-05 18:05:44 +00:00
|
|
|
#endif
|