/*
pybind11/pybind11.h: Main header file of the C++11 python
binding generator library
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#if defined(__INTEL_COMPILER)
# pragma warning push
# pragma warning disable 68 // integer conversion resulted in a change of sign
# pragma warning disable 186 // pointless comparison of unsigned integer with zero
# pragma warning disable 878 // incompatible exception specifications
# pragma warning disable 1334 // the "template" keyword used for syntactic disambiguation may only be used within a template
# pragma warning disable 1682 // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem)
# pragma warning disable 1786 // function "strdup" was declared deprecated
# pragma warning disable 1875 // offsetof applied to non-POD (Plain Old Data) types is nonstandard
# pragma warning disable 2196 // warning #2196: routine is both "inline" and "noinline"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
# pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
# 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: 4702) // warning C4702: unreachable code
# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified
# pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
#elif defined(__GNUG__) && !defined(__clang__)
# 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"
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
# pragma GCC diagnostic ignored "-Wattributes"
# if __GNUC__ >= 7
# pragma GCC diagnostic ignored "-Wnoexcept-type"
# endif
#endif
#include "attr.h"
#include "options.h"
#include "detail/class.h"
#include "detail/init.h"
#include <memory>
#include <vector>
#include <string>
#include <utility>
#if defined(__GNUG__) && !defined(__clang__)
# include <cxxabi.h>
#endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
class cpp_function : public function {
public:
cpp_function() = default;
cpp_function(std::nullptr_t) { }
/// Construct a cpp_function from a vanilla function pointer
template <typename Return, typename... Args, typename... Extra>
cpp_function(Return (*f)(Args...), const Extra&... extra) {
initialize(f, f, extra...);
}
/// Construct a cpp_function from a lambda function (possibly with internal state)
template <typename Func, typename... Extra,
typename = detail::enable_if_t<detail::is_lambda<Func>::value>>
cpp_function(Func &&f, const Extra&... extra) {
initialize(std::forward<Func>(f),
(detail::function_signature_t<Func> *) nullptr, extra...);
}
/// Construct a cpp_function from a class method (non-const, no ref-qualifier)
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...), const Extra&... extra) {
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
(Return (*) (Class *, Arg...)) nullptr, extra...);
}
/// Construct a cpp_function from a class method (non-const, lvalue ref-qualifier)
/// A copy of the overload for non-const functions without explicit ref-qualifier
/// but with an added `&`.
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*) (Class *, Arg...)) nullptr, extra...);
}
/// Construct a cpp_function from a class method (const, no ref-qualifier)
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...) const, const Extra&... extra) {
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
}
/// Construct a cpp_function from a class method (const, lvalue ref-qualifier)
/// A copy of the overload for const functions without explicit ref-qualifier
/// but with an added `&`.
template <typename Return, typename Class, typename... Arg, typename... Extra>
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
}
/// Return the function name
object name() const { return attr("__name__"); }
protected:
struct InitializingFunctionRecordDeleter {
// `destruct(function_record, false)`: `initialize_generic` copies strings and
// takes care of cleaning up in case of exceptions. So pass `false` to `free_strings`.
void operator()(detail::function_record * rec) { destruct(rec, false); }
};
using unique_function_record = std::unique_ptr<detail::function_record, InitializingFunctionRecordDeleter>;
/// Space optimization: don't inline this frequently instantiated fragment
PYBIND11_NOINLINE unique_function_record make_function_record() {
return unique_function_record(new detail::function_record());
}
/// Special internal constructor for functors, lambda functions, etc.
template <typename Func, typename Return, typename... Args, typename... Extra>
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
using namespace detail;
struct capture { remove_reference_t<Func> f; };
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
// The unique_ptr makes sure nothing is leaked in case of an exception.
auto unique_rec = make_function_record();
auto rec = unique_rec.get();
/* Store the capture object directly in the function record if there is enough space */
if (sizeof(capture) <= sizeof(rec->data)) {
/* 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. */
#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wplacement-new"
#endif
new ((capture *) &rec->data) capture { std::forward<Func>(f) };
#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic pop
#endif
if (!std::is_trivially_destructible<Func>::value)
rec->free_data = [](function_record *r) { ((capture *) &r->data)->~capture(); };
} else {
rec->data[0] = new capture { std::forward<Func>(f) };
rec->free_data = [](function_record *r) { delete ((capture *) r->data[0]); };
}
/* Type casters for the function arguments and return value */
using cast_in = argument_loader<Args...>;
using cast_out = make_caster<
conditional_t<std::is_void<Return>::value, void_type, Return>
>;
static_assert(expected_num_args<Extra...>(sizeof...(Args), cast_in::has_args, cast_in::has_kwargs),
"The number of argument annotations does not match the number of function arguments");
/* Dispatch code which converts function arguments and performs the actual function call */
rec->impl = [](function_call &call) -> handle {
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args_converter.load_args(call))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
process_attributes<Extra...>::precall(call);
/* Get a pointer to the capture object */
auto data = (sizeof(capture) <= sizeof(call.func.data)
? &call.func.data : call.func.data[0]);
auto *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
return_value_policy policy = return_value_policy_override<Return>::policy(call.func.policy);
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t<Extra...>;
/* Perform the function call */
handle result = cast_out::cast(
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
/* Invoke call policy post-call hook */
process_attributes<Extra...>::postcall(call, result);
return result;
};
/* Process any user-provided function attributes */
process_attributes<Extra...>::init(extra..., rec);
{
constexpr bool has_kw_only_args = any_of<std::is_same<kw_only, Extra>...>::value,
has_pos_only_args = any_of<std::is_same<pos_only, Extra>...>::value,
has_args = any_of<std::is_same<args, Args>...>::value,
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
static_assert(has_arg_annotations || !has_kw_only_args, "py::kw_only requires the use of argument annotations");
static_assert(has_arg_annotations || !has_pos_only_args, "py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the argument)");
static_assert(!(has_args && has_kw_only_args), "py::kw_only cannot be combined with a py::args argument");
}
/* Generate a readable signature describing the function's arguments and return value types */
static constexpr auto signature = _("(") + cast_in::arg_names + _(") -> ") + cast_out::name;
PYBIND11_DESCR_CONSTEXPR auto types = decltype(signature)::types();
/* Register the function with Python from generic (non-templated) code */
// Pass on the ownership over the `unique_rec` to `initialize_generic`. `rec` stays valid.
initialize_generic(std::move(unique_rec), signature.text, types.data(), sizeof...(Args));
if (cast_in::has_args) rec->has_args = true;
if (cast_in::has_kwargs) rec->has_kwargs = true;
/* 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] = const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
}
}
// Utility class that keeps track of all duplicated strings, and cleans them up in its destructor,
// unless they are released. Basically a RAII-solution to deal with exceptions along the way.
class strdup_guard {
public:
~strdup_guard() {
for (auto s : strings)
std::free(s);
}
char *operator()(const char *s) {
auto t = strdup(s);
strings.push_back(t);
return t;
}
void release() {
strings.clear();
}
private:
std::vector<char *> strings;
};
/// Register a function call with Python (generic non-templated code goes here)
void initialize_generic(unique_function_record &&unique_rec, const char *text,
const std::type_info *const *types, size_t args) {
// Do NOT receive `unique_rec` by value. If this function fails to move out the unique_ptr,
// we do not want this to destuct the pointer. `initialize` (the caller) still relies on the
// pointee being alive after this call. Only move out if a `capsule` is going to keep it alive.
auto rec = unique_rec.get();
// Keep track of strdup'ed strings, and clean them up as long as the function's capsule
// has not taken ownership yet (when `unique_rec.release()` is called).
// Note: This cannot easily be fixed by a `unique_ptr` with custom deleter, because the strings
// are only referenced before strdup'ing. So only *after* the following block could `destruct`
// safely be called, but even then, `repr` could still throw in the middle of copying all strings.
strdup_guard guarded_strdup;
/* Create copies of all referenced C-style strings */
rec->name = guarded_strdup(rec->name ? rec->name : "");
if (rec->doc) rec->doc = guarded_strdup(rec->doc);
for (auto &a: rec->args) {
if (a.name)
a.name = guarded_strdup(a.name);
if (a.descr)
a.descr = guarded_strdup(a.descr);
else if (a.value)
a.descr = guarded_strdup(repr(a.value).cast<std::string>().c_str());
}
rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__");
#if !defined(NDEBUG) && !defined(PYBIND11_DISABLE_NEW_STYLE_INIT_WARNING)
if (rec->is_constructor && !rec->is_new_style_constructor) {
const auto class_name = detail::get_fully_qualified_tp_name((PyTypeObject *) rec->scope.ptr());
const auto func_name = std::string(rec->name);
PyErr_WarnEx(
PyExc_FutureWarning,
("pybind11-bound class '" + class_name + "' is using an old-style "
"placement-new '" + func_name + "' which has been deprecated. See "
"the upgrade guide in pybind11's docs. This message is only visible "
"when compiled in debug mode.").c_str(), 0
);
}
#endif
/* Generate a proper function signature */
std::string signature;
size_t type_index = 0, arg_index = 0;
for (auto *pc = text; *pc != '\0'; ++pc) {
const auto c = *pc;
if (c == '{') {
// Write arg name for everything except *args and **kwargs.
if (*(pc + 1) == '*')
continue;
// Separator for keyword-only arguments, placed before the kw
// arguments start
if (rec->nargs_kw_only > 0 && arg_index + rec->nargs_kw_only == args)
signature += "*, ";
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
signature += rec->args[arg_index].name;
} else if (arg_index == 0 && rec->is_method) {
signature += "self";
} else {
signature += "arg" + std::to_string(arg_index - (rec->is_method ? 1 : 0));
}
signature += ": ";
} else if (c == '}') {
// Write default value if available.
if (arg_index < rec->args.size() && rec->args[arg_index].descr) {
signature += " = ";
signature += rec->args[arg_index].descr;
}
// Separator for positional-only arguments (placed after the
// argument, rather than before like *
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only)
signature += ", /";
arg_index++;
} else if (c == '%') {
const std::type_info *t = types[type_index++];
if (!t)
pybind11_fail("Internal error while parsing type signature (1)");
if (auto tinfo = detail::get_type_info(*t)) {
handle th((PyObject *) tinfo->type);
signature +=
th.attr("__module__").cast<std::string>() + "." +
th.attr("__qualname__").cast<std::string>(); // Python 3.3+, but we backport it to earlier versions
} else if (rec->is_new_style_constructor && arg_index == 0) {
// A new-style `__init__` takes `self` as `value_and_holder`.
// Rewrite it to the proper class type.
signature +=
rec->scope.attr("__module__").cast<std::string>() + "." +
Loading ...