mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Add py::reinterpret_borrow<T>()/steal<T>() for low-level unchecked casts
The pytype converting constructors are convenient and safe for user code, but for library internals the additional type checks and possible conversions are sometimes not desired. `reinterpret_borrow<T>()` and `reinterpret_steal<T>()` serve as the low-level unsafe counterparts of `cast<T>()`. This deprecates the `object(handle, bool)` constructor. Renamed `borrowed` parameter to `is_borrowed` to avoid shadowing warnings on MSVC.
This commit is contained in:
parent
e18bc02fc9
commit
c7ac16bb2e
@ -216,7 +216,7 @@ public:
|
||||
auto const &type_dict = get_internals().registered_types_py;
|
||||
bool new_style_class = PyType_Check(tobj);
|
||||
if (type_dict.find(tobj) == type_dict.end() && new_style_class && tobj->tp_bases) {
|
||||
tuple parents(tobj->tp_bases, true);
|
||||
auto parents = reinterpret_borrow<tuple>(tobj->tp_bases);
|
||||
for (handle parent : parents) {
|
||||
bool result = load(src, convert, (PyTypeObject *) parent.ptr());
|
||||
if (result)
|
||||
@ -237,7 +237,7 @@ public:
|
||||
/* Perform an implicit conversion */
|
||||
if (convert) {
|
||||
for (auto &converter : typeinfo->implicit_conversions) {
|
||||
temp = object(converter(src.ptr(), typeinfo->type), false);
|
||||
temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type));
|
||||
if (load(temp, false))
|
||||
return true;
|
||||
}
|
||||
@ -284,7 +284,7 @@ public:
|
||||
return handle((PyObject *) it_i->second).inc_ref();
|
||||
}
|
||||
|
||||
object inst(PyType_GenericAlloc(tinfo->type, 0), false);
|
||||
auto inst = reinterpret_steal<object>(PyType_GenericAlloc(tinfo->type, 0));
|
||||
|
||||
auto wrapper = (instance<void> *) inst.ptr();
|
||||
|
||||
@ -487,9 +487,9 @@ public:
|
||||
#endif
|
||||
PyErr_Clear();
|
||||
if (type_error && PyNumber_Check(src.ptr())) {
|
||||
object tmp(std::is_floating_point<T>::value
|
||||
? PyNumber_Float(src.ptr())
|
||||
: PyNumber_Long(src.ptr()), true);
|
||||
auto tmp = reinterpret_borrow<object>(std::is_floating_point<T>::value
|
||||
? PyNumber_Float(src.ptr())
|
||||
: PyNumber_Long(src.ptr()));
|
||||
PyErr_Clear();
|
||||
return load(tmp, false);
|
||||
}
|
||||
@ -544,7 +544,7 @@ public:
|
||||
|
||||
/* Check if this is a capsule */
|
||||
if (isinstance<capsule>(h)) {
|
||||
value = capsule(h, true);
|
||||
value = reinterpret_borrow<capsule>(h);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -596,7 +596,7 @@ public:
|
||||
if (!src) {
|
||||
return false;
|
||||
} else if (PyUnicode_Check(load_src.ptr())) {
|
||||
temp = object(PyUnicode_AsUTF8String(load_src.ptr()), false);
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(load_src.ptr()));
|
||||
if (!temp) { PyErr_Clear(); return false; } // UnicodeEncodeError
|
||||
load_src = temp;
|
||||
}
|
||||
@ -637,7 +637,7 @@ public:
|
||||
if (!src) {
|
||||
return false;
|
||||
} else if (!PyUnicode_Check(load_src.ptr())) {
|
||||
temp = object(PyUnicode_FromObject(load_src.ptr()), false);
|
||||
temp = reinterpret_steal<object>(PyUnicode_FromObject(load_src.ptr()));
|
||||
if (!temp) { PyErr_Clear(); return false; }
|
||||
load_src = temp;
|
||||
}
|
||||
@ -646,10 +646,10 @@ public:
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
buffer = PyUnicode_AsWideCharString(load_src.ptr(), &length);
|
||||
#else
|
||||
temp = object(
|
||||
temp = reinterpret_steal<object>(
|
||||
sizeof(wchar_t) == sizeof(short)
|
||||
? PyUnicode_AsUTF16String(load_src.ptr())
|
||||
: PyUnicode_AsUTF32String(load_src.ptr()), false);
|
||||
: PyUnicode_AsUTF32String(load_src.ptr()));
|
||||
if (temp) {
|
||||
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), (char **) &buffer, &length);
|
||||
if (err == -1) { buffer = nullptr; } // TypeError
|
||||
@ -730,8 +730,8 @@ public:
|
||||
}
|
||||
|
||||
static handle cast(const type &src, return_value_policy policy, handle parent) {
|
||||
object o1 = object(make_caster<T1>::cast(src.first, policy, parent), false);
|
||||
object o2 = object(make_caster<T2>::cast(src.second, policy, parent), false);
|
||||
auto o1 = reinterpret_steal<object>(make_caster<T1>::cast(src.first, policy, parent));
|
||||
auto o2 = reinterpret_steal<object>(make_caster<T2>::cast(src.second, policy, parent));
|
||||
if (!o1 || !o2)
|
||||
return handle();
|
||||
tuple result(2);
|
||||
@ -846,7 +846,7 @@ protected:
|
||||
/* Implementation: Convert a C++ tuple into a Python tuple */
|
||||
template <size_t ... Indices> static handle cast(const type &src, return_value_policy policy, handle parent, index_sequence<Indices...>) {
|
||||
std::array<object, size> entries {{
|
||||
object(make_caster<Tuple>::cast(std::get<Indices>(src), policy, parent), false)...
|
||||
reinterpret_steal<object>(make_caster<Tuple>::cast(std::get<Indices>(src), policy, parent))...
|
||||
}};
|
||||
for (const auto &entry: entries)
|
||||
if (!entry)
|
||||
@ -905,7 +905,7 @@ public:
|
||||
auto const &type_dict = get_internals().registered_types_py;
|
||||
bool new_style_class = PyType_Check(tobj);
|
||||
if (type_dict.find(tobj) == type_dict.end() && new_style_class && tobj->tp_bases) {
|
||||
tuple parents(tobj->tp_bases, true);
|
||||
auto parents = reinterpret_borrow<tuple>(tobj->tp_bases);
|
||||
for (handle parent : parents) {
|
||||
bool result = load(src, convert, (PyTypeObject *) parent.ptr());
|
||||
if (result)
|
||||
@ -919,7 +919,7 @@ public:
|
||||
|
||||
if (convert) {
|
||||
for (auto &converter : typeinfo->implicit_conversions) {
|
||||
temp = object(converter(src.ptr(), typeinfo->type), false);
|
||||
temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type));
|
||||
if (load(temp, false))
|
||||
return true;
|
||||
}
|
||||
@ -1000,7 +1000,7 @@ struct pyobject_caster {
|
||||
bool load(handle src, bool /* convert */) {
|
||||
if (!isinstance<type>(src))
|
||||
return false;
|
||||
value = type(src, true);
|
||||
value = reinterpret_borrow<type>(src);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1070,6 +1070,7 @@ template <typename T> make_caster<T> load_type(const handle &handle) {
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
// pytype -> C++ type
|
||||
template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0>
|
||||
T cast(const handle &handle) {
|
||||
static_assert(!detail::cast_is_temporary_value_reference<T>::value,
|
||||
@ -1078,9 +1079,11 @@ T cast(const handle &handle) {
|
||||
return detail::load_type<T>(handle).operator typename type_caster::template cast_op_type<T>();
|
||||
}
|
||||
|
||||
// pytype -> pytype (calls converting constructor)
|
||||
template <typename T, detail::enable_if_t<detail::is_pyobject<T>::value, int> = 0>
|
||||
T cast(const handle &handle) { return {handle, true}; }
|
||||
T cast(const handle &handle) { return T(reinterpret_borrow<object>(handle)); }
|
||||
|
||||
// C++ type -> py::object
|
||||
template <typename T, detail::enable_if_t<!detail::is_pyobject<T>::value, int> = 0>
|
||||
object cast(const T &value, return_value_policy policy = return_value_policy::automatic_reference,
|
||||
handle parent = handle()) {
|
||||
@ -1088,7 +1091,7 @@ object cast(const T &value, return_value_policy policy = return_value_policy::au
|
||||
policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy;
|
||||
else if (policy == return_value_policy::automatic_reference)
|
||||
policy = std::is_pointer<T>::value ? return_value_policy::reference : return_value_policy::copy;
|
||||
return object(detail::make_caster<T>::cast(value, policy, parent), false);
|
||||
return reinterpret_steal<object>(detail::make_caster<T>::cast(value, policy, parent));
|
||||
}
|
||||
|
||||
template <typename T> T handle::cast() const { return pybind11::cast<T>(*this); }
|
||||
@ -1162,8 +1165,8 @@ template <return_value_policy policy = return_value_policy::automatic_reference,
|
||||
typename... Args> tuple make_tuple(Args&&... args_) {
|
||||
const size_t size = sizeof...(Args);
|
||||
std::array<object, size> args {
|
||||
{ object(detail::make_caster<Args>::cast(
|
||||
std::forward<Args>(args_), policy, nullptr), false)... }
|
||||
{ reinterpret_steal<object>(detail::make_caster<Args>::cast(
|
||||
std::forward<Args>(args_), policy, nullptr))... }
|
||||
};
|
||||
for (auto &arg_value : args) {
|
||||
if (!arg_value) {
|
||||
@ -1195,7 +1198,9 @@ struct arg_v : arg {
|
||||
template <typename T>
|
||||
arg_v(const char *name, T &&x, const char *descr = nullptr)
|
||||
: arg(name),
|
||||
value(detail::make_caster<T>::cast(x, return_value_policy::automatic, handle()), false),
|
||||
value(reinterpret_steal<object>(
|
||||
detail::make_caster<T>::cast(x, return_value_policy::automatic, {})
|
||||
)),
|
||||
descr(descr)
|
||||
#if !defined(NDEBUG)
|
||||
, type(type_id<T>())
|
||||
@ -1256,10 +1261,10 @@ public:
|
||||
|
||||
/// Call a Python function and pass the collected arguments
|
||||
object call(PyObject *ptr) const {
|
||||
auto result = object(PyObject_CallObject(ptr, m_args.ptr()), false);
|
||||
PyObject *result = PyObject_CallObject(ptr, m_args.ptr());
|
||||
if (!result)
|
||||
throw error_already_set();
|
||||
return result;
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1289,16 +1294,16 @@ public:
|
||||
|
||||
/// Call a Python function and pass the collected arguments
|
||||
object call(PyObject *ptr) const {
|
||||
auto result = object(PyObject_Call(ptr, m_args.ptr(), m_kwargs.ptr()), false);
|
||||
PyObject *result = PyObject_Call(ptr, m_args.ptr(), m_kwargs.ptr());
|
||||
if (!result)
|
||||
throw error_already_set();
|
||||
return result;
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void process(list &args_list, T &&x) {
|
||||
auto o = object(detail::make_caster<T>::cast(std::forward<T>(x), policy, nullptr), false);
|
||||
auto o = reinterpret_steal<object>(detail::make_caster<T>::cast(std::forward<T>(x), policy, {}));
|
||||
if (!o) {
|
||||
#if defined(NDEBUG)
|
||||
argument_cast_error();
|
||||
@ -1335,7 +1340,7 @@ private:
|
||||
void process(list &/*args_list*/, detail::kwargs_proxy kp) {
|
||||
if (!kp)
|
||||
return;
|
||||
for (const auto &k : dict(kp, true)) {
|
||||
for (const auto &k : reinterpret_borrow<dict>(kp)) {
|
||||
if (m_kwargs.contains(k.first)) {
|
||||
#if defined(NDEBUG)
|
||||
multiple_values_error();
|
||||
|
@ -182,7 +182,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
if (!src)
|
||||
return false;
|
||||
|
||||
object obj(src, true);
|
||||
auto obj = reinterpret_borrow<object>(src);
|
||||
object sparse_module = module::import("scipy.sparse");
|
||||
object matrix_type = sparse_module.attr(
|
||||
rowMajor ? "csr_matrix" : "csc_matrix");
|
||||
|
@ -31,7 +31,7 @@ enum eval_mode {
|
||||
template <eval_mode mode = eval_expr>
|
||||
object eval(str expr, object global = object(), object local = object()) {
|
||||
if (!global) {
|
||||
global = object(PyEval_GetGlobals(), true);
|
||||
global = reinterpret_borrow<object>(PyEval_GetGlobals());
|
||||
if (!global)
|
||||
global = dict();
|
||||
}
|
||||
@ -50,17 +50,16 @@ object eval(str expr, object global = object(), object local = object()) {
|
||||
default: pybind11_fail("invalid evaluation mode");
|
||||
}
|
||||
|
||||
object result(PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr()), false);
|
||||
|
||||
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
|
||||
if (!result)
|
||||
throw error_already_set();
|
||||
return result;
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
template <eval_mode mode = eval_statements>
|
||||
object eval_file(str fname, object global = object(), object local = object()) {
|
||||
if (!global) {
|
||||
global = object(PyEval_GetGlobals(), true);
|
||||
global = reinterpret_borrow<object>(PyEval_GetGlobals());
|
||||
if (!global)
|
||||
global = dict();
|
||||
}
|
||||
@ -83,9 +82,9 @@ object eval_file(str fname, object global = object(), object local = object()) {
|
||||
FILE *f = _Py_fopen(fname.ptr(), "r");
|
||||
#else
|
||||
/* No unicode support in open() :( */
|
||||
object fobj(PyFile_FromString(
|
||||
auto fobj = reinterpret_steal<object>(PyFile_FromString(
|
||||
const_cast<char *>(fname_str.c_str()),
|
||||
const_cast<char*>("r")), false);
|
||||
const_cast<char*>("r")));
|
||||
FILE *f = nullptr;
|
||||
if (fobj)
|
||||
f = PyFile_AsFile(fobj.ptr());
|
||||
@ -96,14 +95,11 @@ object eval_file(str fname, object global = object(), object local = object()) {
|
||||
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
|
||||
}
|
||||
|
||||
object result(PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
|
||||
local.ptr(), closeFile),
|
||||
false);
|
||||
|
||||
PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
|
||||
local.ptr(), closeFile);
|
||||
if (!result)
|
||||
throw error_already_set();
|
||||
|
||||
return result;
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
NAMESPACE_END(pybind11)
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
captured variables), in which case the roundtrip can be avoided.
|
||||
*/
|
||||
if (PyCFunction_Check(src_.ptr())) {
|
||||
capsule c(PyCFunction_GetSelf(src_.ptr()), true);
|
||||
auto c = reinterpret_borrow<capsule>(PyCFunction_GetSelf(src_.ptr()));
|
||||
auto rec = (function_record *) c;
|
||||
using FunctionType = Return (*) (Args...);
|
||||
|
||||
@ -47,7 +47,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
object src(src_, true);
|
||||
auto src = reinterpret_borrow<object>(src_);
|
||||
value = [src](Args... args) -> Return {
|
||||
gil_scoped_acquire acq;
|
||||
object retval(src(std::move(args)...));
|
||||
|
@ -239,7 +239,7 @@ public:
|
||||
PyObject *ptr = nullptr;
|
||||
if (!detail::npy_api::get().PyArray_DescrConverter_(args.release().ptr(), &ptr) || !ptr)
|
||||
throw error_already_set();
|
||||
return object(ptr, false);
|
||||
return reinterpret_steal<dtype>(ptr);
|
||||
}
|
||||
|
||||
/// Return dtype associated with a C++ type.
|
||||
@ -266,7 +266,7 @@ private:
|
||||
static object _dtype_from_pep3118() {
|
||||
static PyObject *obj = module::import("numpy.core._internal")
|
||||
.attr("_dtype_from_pep3118").cast<object>().release().ptr();
|
||||
return object(obj, true);
|
||||
return reinterpret_borrow<object>(obj);
|
||||
}
|
||||
|
||||
dtype strip_padding() {
|
||||
@ -279,7 +279,7 @@ private:
|
||||
std::vector<field_descr> field_descriptors;
|
||||
|
||||
for (auto field : attr("fields").attr("items")()) {
|
||||
auto spec = object(field, true).cast<tuple>();
|
||||
auto spec = field.cast<tuple>();
|
||||
auto name = spec[0].cast<pybind11::str>();
|
||||
auto format = spec[1].cast<tuple>()[0].cast<dtype>();
|
||||
auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>();
|
||||
@ -326,22 +326,22 @@ public:
|
||||
if (base && ptr) {
|
||||
if (isinstance<array>(base))
|
||||
/* Copy flags from base (except baseship bit) */
|
||||
flags = array(base, true).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
|
||||
flags = reinterpret_borrow<array>(base).flags() & ~detail::npy_api::NPY_ARRAY_OWNDATA_;
|
||||
else
|
||||
/* Writable by default, easy to downgrade later on if needed */
|
||||
flags = detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||
}
|
||||
|
||||
object tmp(api.PyArray_NewFromDescr_(
|
||||
auto tmp = reinterpret_steal<object>(api.PyArray_NewFromDescr_(
|
||||
api.PyArray_Type_, descr.release().ptr(), (int) ndim, (Py_intptr_t *) shape.data(),
|
||||
(Py_intptr_t *) strides.data(), const_cast<void *>(ptr), flags, nullptr), false);
|
||||
(Py_intptr_t *) strides.data(), const_cast<void *>(ptr), flags, nullptr));
|
||||
if (!tmp)
|
||||
pybind11_fail("NumPy: unable to create array!");
|
||||
if (ptr) {
|
||||
if (base) {
|
||||
PyArray_GET_(tmp.ptr(), base) = base.inc_ref().ptr();
|
||||
} else {
|
||||
tmp = object(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */), false);
|
||||
tmp = reinterpret_steal<object>(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */));
|
||||
}
|
||||
}
|
||||
m_ptr = tmp.release().ptr();
|
||||
@ -374,7 +374,7 @@ public:
|
||||
|
||||
/// Array descriptor (dtype)
|
||||
pybind11::dtype dtype() const {
|
||||
return object(PyArray_GET_(m_ptr, descr), true);
|
||||
return reinterpret_borrow<pybind11::dtype>(PyArray_GET_(m_ptr, descr));
|
||||
}
|
||||
|
||||
/// Total number of elements
|
||||
@ -399,7 +399,7 @@ public:
|
||||
|
||||
/// Base object
|
||||
object base() const {
|
||||
return object(PyArray_GET_(m_ptr, base), true);
|
||||
return reinterpret_borrow<object>(PyArray_GET_(m_ptr, base));
|
||||
}
|
||||
|
||||
/// Dimensions of the array
|
||||
@ -474,14 +474,14 @@ public:
|
||||
/// Return a new view with all of the dimensions of length 1 removed
|
||||
array squeeze() {
|
||||
auto& api = detail::npy_api::get();
|
||||
return array(api.PyArray_Squeeze_(m_ptr), false);
|
||||
return reinterpret_steal<array>(api.PyArray_Squeeze_(m_ptr));
|
||||
}
|
||||
|
||||
/// Ensure that the argument is a NumPy array
|
||||
static array ensure(object input, int ExtraFlags = 0) {
|
||||
auto& api = detail::npy_api::get();
|
||||
return array(api.PyArray_FromAny_(
|
||||
input.release().ptr(), nullptr, 0, 0, detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr), false);
|
||||
return reinterpret_steal<array>(api.PyArray_FromAny_(
|
||||
input.release().ptr(), nullptr, 0, 0, detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr));
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -542,7 +542,7 @@ template <typename T, int ExtraFlags = array::forcecast> class array_t : public
|
||||
public:
|
||||
array_t() : array() { }
|
||||
|
||||
array_t(handle h, bool borrowed) : array(h, borrowed) { m_ptr = ensure_(m_ptr); }
|
||||
array_t(handle h, bool is_borrowed) : array(h, is_borrowed) { m_ptr = ensure_(m_ptr); }
|
||||
|
||||
array_t(const object &o) : array(o) { m_ptr = ensure_(m_ptr); }
|
||||
|
||||
@ -668,7 +668,7 @@ public:
|
||||
enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned<T>::value ? 1 : 0)] };
|
||||
static pybind11::dtype dtype() {
|
||||
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value))
|
||||
return object(ptr, true);
|
||||
return reinterpret_borrow<pybind11::dtype>(ptr);
|
||||
pybind11_fail("Unsupported buffer format!");
|
||||
}
|
||||
template <typename T2 = T, enable_if_t<std::is_signed<T2>::value, int> = 0>
|
||||
@ -683,7 +683,7 @@ template <typename T> constexpr const int npy_format_descriptor<
|
||||
enum { value = npy_api::NumPyName }; \
|
||||
static pybind11::dtype dtype() { \
|
||||
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) \
|
||||
return object(ptr, true); \
|
||||
return reinterpret_borrow<pybind11::dtype>(ptr); \
|
||||
pybind11_fail("Unsupported buffer format!"); \
|
||||
} \
|
||||
static PYBIND11_DESCR name() { return _(Name); } }
|
||||
@ -778,7 +778,7 @@ struct npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>> {
|
||||
static PYBIND11_DESCR name() { return _("struct"); }
|
||||
|
||||
static pybind11::dtype dtype() {
|
||||
return object(dtype_ptr(), true);
|
||||
return reinterpret_borrow<pybind11::dtype>(dtype_ptr());
|
||||
}
|
||||
|
||||
static std::string format() {
|
||||
@ -801,7 +801,7 @@ private:
|
||||
auto& api = npy_api::get();
|
||||
if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_))
|
||||
return false;
|
||||
if (auto descr = object(api.PyArray_DescrFromScalar_(obj), false)) {
|
||||
if (auto descr = reinterpret_steal<object>(api.PyArray_DescrFromScalar_(obj))) {
|
||||
if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
|
||||
value = ((PyVoidScalarObject_Proxy *) obj)->obval;
|
||||
return true;
|
||||
|
@ -256,7 +256,7 @@ protected:
|
||||
detail::function_record *chain = nullptr, *chain_start = rec;
|
||||
if (rec->sibling) {
|
||||
if (PyCFunction_Check(rec->sibling.ptr())) {
|
||||
capsule rec_capsule(PyCFunction_GetSelf(rec->sibling.ptr()), true);
|
||||
auto rec_capsule = reinterpret_borrow<capsule>(PyCFunction_GetSelf(rec->sibling.ptr()));
|
||||
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 */
|
||||
@ -382,7 +382,7 @@ protected:
|
||||
result = PYBIND11_TRY_NEXT_OVERLOAD;
|
||||
try {
|
||||
for (; it != nullptr; it = it->next) {
|
||||
tuple args_(args, true);
|
||||
auto args_ = reinterpret_borrow<tuple>(args);
|
||||
size_t kwargs_consumed = 0;
|
||||
|
||||
/* For each overload:
|
||||
@ -502,7 +502,7 @@ protected:
|
||||
msg += "\n";
|
||||
}
|
||||
msg += "\nInvoked with: ";
|
||||
tuple args_(args, true);
|
||||
auto args_ = reinterpret_borrow<tuple>(args);
|
||||
for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
|
||||
msg += static_cast<std::string>(pybind11::str(args_[ti]));
|
||||
if ((ti + 1) != args_.size() )
|
||||
@ -565,7 +565,7 @@ public:
|
||||
module def_submodule(const char *name, const char *doc = nullptr) {
|
||||
std::string full_name = std::string(PyModule_GetName(m_ptr))
|
||||
+ std::string(".") + std::string(name);
|
||||
module result(PyImport_AddModule(full_name.c_str()), true);
|
||||
auto result = reinterpret_borrow<module>(PyImport_AddModule(full_name.c_str()));
|
||||
if (doc && options::show_user_defined_docstrings())
|
||||
result.attr("__doc__") = pybind11::str(doc);
|
||||
attr(name) = result;
|
||||
@ -576,7 +576,7 @@ public:
|
||||
PyObject *obj = PyImport_ImportModule(name);
|
||||
if (!obj)
|
||||
throw import_error("Module \"" + std::string(name) + "\" not found!");
|
||||
return module(obj, false);
|
||||
return reinterpret_steal<module>(obj);
|
||||
}
|
||||
|
||||
// Adds an object to the module using the given name. Throws if an object with the given name
|
||||
@ -636,7 +636,7 @@ protected:
|
||||
pybind11_fail("generic_type: type \"" + std::string(rec->name) +
|
||||
"\" is already registered!");
|
||||
|
||||
object name(PYBIND11_FROM_STRING(rec->name), false);
|
||||
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec->name));
|
||||
object scope_module;
|
||||
if (rec->scope) {
|
||||
if (hasattr(rec->scope, rec->name))
|
||||
@ -657,8 +657,8 @@ protected:
|
||||
scope_qualname = rec->scope.attr("__qualname__");
|
||||
object ht_qualname;
|
||||
if (scope_qualname) {
|
||||
ht_qualname = object(PyUnicode_FromFormat(
|
||||
"%U.%U", scope_qualname.ptr(), name.ptr()), false);
|
||||
ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat(
|
||||
"%U.%U", scope_qualname.ptr(), name.ptr()));
|
||||
} else {
|
||||
ht_qualname = name;
|
||||
}
|
||||
@ -684,7 +684,7 @@ protected:
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0));
|
||||
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
||||
|
||||
if (!type_holder || !name)
|
||||
@ -768,7 +768,7 @@ protected:
|
||||
|
||||
/// Helper function which tags all parents of a type using mult. inheritance
|
||||
void mark_parents_nonsimple(PyTypeObject *value) {
|
||||
tuple t(value->tp_bases, true);
|
||||
auto t = reinterpret_borrow<tuple>(value->tp_bases);
|
||||
for (handle h : t) {
|
||||
auto tinfo2 = get_type_info((PyTypeObject *) h.ptr());
|
||||
if (tinfo2)
|
||||
@ -785,10 +785,10 @@ protected:
|
||||
if (ob_type == &PyType_Type) {
|
||||
std::string name_ = std::string(ht_type.tp_name) + "__Meta";
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
object ht_qualname(PyUnicode_FromFormat("%U__Meta", attr("__qualname__").ptr()), false);
|
||||
auto ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat("%U__Meta", attr("__qualname__").ptr()));
|
||||
#endif
|
||||
object name(PYBIND11_FROM_STRING(name_.c_str()), false);
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(name_.c_str()));
|
||||
auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0));
|
||||
if (!type_holder || !name)
|
||||
pybind11_fail("generic_type::metaclass(): unable to create type object!");
|
||||
|
||||
@ -936,7 +936,7 @@ public:
|
||||
static_assert(detail::all_of_t<is_valid_class_option, options...>::value,
|
||||
"Unknown/invalid class_ template parameters provided");
|
||||
|
||||
PYBIND11_OBJECT(class_, detail::generic_type, PyType_Check)
|
||||
PYBIND11_OBJECT(class_, generic_type, PyType_Check)
|
||||
|
||||
template <typename... Extra>
|
||||
class_(handle scope, const char *name, const Extra &... extra) {
|
||||
@ -1117,9 +1117,9 @@ public:
|
||||
}
|
||||
}
|
||||
pybind11::str doc_obj = pybind11::str((rec_fget->doc && pybind11::options::show_user_defined_docstrings()) ? rec_fget->doc : "");
|
||||
object property(
|
||||
const auto property = reinterpret_steal<object>(
|
||||
PyObject_CallFunctionObjArgs((PyObject *) &PyProperty_Type, fget.ptr() ? fget.ptr() : Py_None,
|
||||
fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr), false);
|
||||
fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr(), nullptr));
|
||||
if (rec_fget->class_)
|
||||
attr(name) = property;
|
||||
else
|
||||
@ -1178,8 +1178,8 @@ private:
|
||||
|
||||
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;
|
||||
return h ? (detail::function_record *) reinterpret_borrow<capsule>(PyCFunction_GetSelf(h.ptr()))
|
||||
: nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -102,9 +102,9 @@ protected:
|
||||
class object : public handle {
|
||||
public:
|
||||
object() = default;
|
||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<object>() or reinterpret_steal<object>()")
|
||||
object(handle h, bool is_borrowed) : handle(h) { if (is_borrowed) inc_ref(); }
|
||||
object(const object &o) : handle(o) { inc_ref(); }
|
||||
object(const handle &h, bool borrowed) : handle(h) { if (borrowed) inc_ref(); }
|
||||
object(PyObject *ptr, bool borrowed) : handle(ptr) { if (borrowed) inc_ref(); }
|
||||
object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; }
|
||||
~object() { dec_ref(); }
|
||||
|
||||
@ -135,8 +135,26 @@ public:
|
||||
template <typename T> T cast() const &;
|
||||
// Calling on an object rvalue does a move, if needed and/or possible
|
||||
template <typename T> T cast() &&;
|
||||
|
||||
protected:
|
||||
// Tags for choosing constructors from raw PyObject *
|
||||
struct borrowed_t { }; static constexpr borrowed_t borrowed{};
|
||||
struct stolen_t { }; static constexpr stolen_t stolen{};
|
||||
|
||||
template <typename T> friend T reinterpret_borrow(handle);
|
||||
template <typename T> friend T reinterpret_steal(handle);
|
||||
|
||||
public:
|
||||
// Only accessible from derived classes and the reinterpret_* functions
|
||||
object(handle h, borrowed_t) : handle(h) { inc_ref(); }
|
||||
object(handle h, stolen_t) : handle(h) { }
|
||||
};
|
||||
|
||||
/** The following functions don't do any kind of conversion, they simply declare
|
||||
that a PyObject is a certain type and borrow or steal the reference. */
|
||||
template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed}; }
|
||||
template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen}; }
|
||||
|
||||
/// Check if `obj` is an instance of type `T`
|
||||
template <typename T, detail::enable_if_t<std::is_base_of<object, T>::value, int> = 0>
|
||||
bool isinstance(handle obj) { return T::_check(obj); }
|
||||
@ -158,30 +176,30 @@ inline bool hasattr(handle obj, const char *name) {
|
||||
inline object getattr(handle obj, handle name) {
|
||||
PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr());
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, false};
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
inline object getattr(handle obj, const char *name) {
|
||||
PyObject *result = PyObject_GetAttrString(obj.ptr(), name);
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, false};
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
inline object getattr(handle obj, handle name, handle default_) {
|
||||
if (PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr())) {
|
||||
return {result, false};
|
||||
return reinterpret_steal<object>(result);
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
return {default_, true};
|
||||
return reinterpret_borrow<object>(default_);
|
||||
}
|
||||
}
|
||||
|
||||
inline object getattr(handle obj, const char *name, handle default_) {
|
||||
if (PyObject *result = PyObject_GetAttrString(obj.ptr(), name)) {
|
||||
return {result, false};
|
||||
return reinterpret_steal<object>(result);
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
return {default_, true};
|
||||
return reinterpret_borrow<object>(default_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +236,7 @@ public:
|
||||
void operator=(const object &o) && { std::move(*this).operator=(handle(o)); }
|
||||
void operator=(const object &o) & { operator=(handle(o)); }
|
||||
void operator=(handle value) && { Policy::set(obj, key, value); }
|
||||
void operator=(handle value) & { get_cache() = object(value, true); }
|
||||
void operator=(handle value) & { get_cache() = reinterpret_borrow<object>(value); }
|
||||
|
||||
template <typename T = Policy>
|
||||
PYBIND11_DEPRECATED("Use of obj.attr(...) as bool is deprecated in favor of pybind11::hasattr(obj, ...)")
|
||||
@ -267,7 +285,7 @@ struct generic_item {
|
||||
static object get(handle obj, handle key) {
|
||||
PyObject *result = PyObject_GetItem(obj.ptr(), key.ptr());
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, false};
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
static void set(handle obj, handle key, handle val) {
|
||||
@ -281,7 +299,7 @@ struct sequence_item {
|
||||
static object get(handle obj, size_t index) {
|
||||
PyObject *result = PySequence_GetItem(obj.ptr(), static_cast<ssize_t>(index));
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, true};
|
||||
return reinterpret_borrow<object>(result);
|
||||
}
|
||||
|
||||
static void set(handle obj, size_t index, handle val) {
|
||||
@ -298,7 +316,7 @@ struct list_item {
|
||||
static object get(handle obj, size_t index) {
|
||||
PyObject *result = PyList_GetItem(obj.ptr(), static_cast<ssize_t>(index));
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, true};
|
||||
return reinterpret_borrow<object>(result);
|
||||
}
|
||||
|
||||
static void set(handle obj, size_t index, handle val) {
|
||||
@ -315,7 +333,7 @@ struct tuple_item {
|
||||
static object get(handle obj, size_t index) {
|
||||
PyObject *result = PyTuple_GetItem(obj.ptr(), static_cast<ssize_t>(index));
|
||||
if (!result) { throw error_already_set(); }
|
||||
return {result, true};
|
||||
return reinterpret_borrow<object>(result);
|
||||
}
|
||||
|
||||
static void set(handle obj, size_t index, handle val) {
|
||||
@ -390,23 +408,30 @@ class unpacking_collector;
|
||||
|
||||
NAMESPACE_END(detail)
|
||||
|
||||
// TODO: After the deprecated constructors are removed, this macro can be simplified by
|
||||
// inheriting ctors: `using Parent::Parent`. It's not an option right now because
|
||||
// the `using` statement triggers the parent deprecation warning even if the ctor
|
||||
// isn't even used.
|
||||
#define PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||
public: \
|
||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<"#Name">() or reinterpret_steal<"#Name">()") \
|
||||
Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed) : Parent(h, stolen)) { } \
|
||||
Name(handle h, borrowed_t) : Parent(h, borrowed) { } \
|
||||
Name(handle h, stolen_t) : Parent(h, stolen) { } \
|
||||
PYBIND11_DEPRECATED("Use py::isinstance<py::python_type>(obj) instead") \
|
||||
bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } \
|
||||
static bool _check(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); }
|
||||
|
||||
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
|
||||
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||
Name(handle h, bool borrowed) : Name(object(h, borrowed)) { } \
|
||||
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
|
||||
Name(const object &o) : Parent(ConvertFun(o.ptr()), false) { if (!m_ptr) throw error_already_set(); }
|
||||
Name(const object &o) : Parent(ConvertFun(o.ptr()), stolen) { if (!m_ptr) throw error_already_set(); }
|
||||
|
||||
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \
|
||||
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||
Name(handle h, bool borrowed) : Parent(h, borrowed) { } \
|
||||
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
|
||||
Name(const object &o) : Parent(o) { }
|
||||
Name(const object &o) : Parent(o) { } \
|
||||
Name(object &&o) : Parent(std::move(o)) { }
|
||||
|
||||
#define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \
|
||||
PYBIND11_OBJECT(Name, Parent, CheckFun) \
|
||||
@ -448,7 +473,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void advance() { value = object(PyIter_Next(m_ptr), false); }
|
||||
void advance() { value = reinterpret_steal<object>(PyIter_Next(m_ptr)); }
|
||||
|
||||
private:
|
||||
object value = {};
|
||||
@ -467,13 +492,13 @@ public:
|
||||
PYBIND11_OBJECT_CVT(str, object, detail::PyUnicode_Check_Permissive, raw_str)
|
||||
|
||||
str(const char *c, size_t n)
|
||||
: object(PyUnicode_FromStringAndSize(c, (ssize_t) n), false) {
|
||||
: object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||
}
|
||||
|
||||
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
|
||||
str(const char *c = "")
|
||||
: object(PyUnicode_FromString(c), false) {
|
||||
: object(PyUnicode_FromString(c), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||
}
|
||||
|
||||
@ -481,12 +506,12 @@ public:
|
||||
|
||||
explicit str(const bytes &b);
|
||||
|
||||
explicit str(handle h) : object(raw_str(h.ptr()), false) { }
|
||||
explicit str(handle h) : object(raw_str(h.ptr()), stolen) { }
|
||||
|
||||
operator std::string() const {
|
||||
object temp = *this;
|
||||
if (PyUnicode_Check(m_ptr)) {
|
||||
temp = object(PyUnicode_AsUTF8String(m_ptr), false);
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(m_ptr));
|
||||
if (!temp)
|
||||
pybind11_fail("Unable to extract string contents! (encoding issue)");
|
||||
}
|
||||
@ -526,12 +551,12 @@ public:
|
||||
|
||||
// Allow implicit conversion:
|
||||
bytes(const char *c = "")
|
||||
: object(PYBIND11_BYTES_FROM_STRING(c), false) {
|
||||
: object(PYBIND11_BYTES_FROM_STRING(c), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||
}
|
||||
|
||||
bytes(const char *c, size_t n)
|
||||
: object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), false) {
|
||||
: object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||
}
|
||||
|
||||
@ -552,7 +577,7 @@ public:
|
||||
inline bytes::bytes(const pybind11::str &s) {
|
||||
object temp = s;
|
||||
if (PyUnicode_Check(s.ptr())) {
|
||||
temp = object(PyUnicode_AsUTF8String(s.ptr()), false);
|
||||
temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr()));
|
||||
if (!temp)
|
||||
pybind11_fail("Unable to extract string contents! (encoding issue)");
|
||||
}
|
||||
@ -560,7 +585,7 @@ inline bytes::bytes(const pybind11::str &s) {
|
||||
ssize_t length;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length))
|
||||
pybind11_fail("Unable to extract string contents! (invalid type)");
|
||||
auto obj = object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length), false);
|
||||
auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length));
|
||||
if (!obj)
|
||||
pybind11_fail("Could not allocate bytes object!");
|
||||
m_ptr = obj.release().ptr();
|
||||
@ -571,7 +596,7 @@ inline str::str(const bytes& b) {
|
||||
ssize_t length;
|
||||
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length))
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
auto obj = object(PyUnicode_FromStringAndSize(buffer, (ssize_t) length), false);
|
||||
auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, (ssize_t) length));
|
||||
if (!obj)
|
||||
pybind11_fail("Could not allocate string object!");
|
||||
m_ptr = obj.release().ptr();
|
||||
@ -580,15 +605,15 @@ inline str::str(const bytes& b) {
|
||||
class none : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT(none, object, detail::PyNone_Check)
|
||||
none() : object(Py_None, true) { }
|
||||
none() : object(Py_None, borrowed) { }
|
||||
};
|
||||
|
||||
class bool_ : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool)
|
||||
bool_() : object(Py_False, true) { }
|
||||
bool_() : object(Py_False, borrowed) { }
|
||||
// Allow implicit conversion from and to `bool`:
|
||||
bool_(bool value) : object(value ? Py_True : Py_False, true) { }
|
||||
bool_(bool value) : object(value ? Py_True : Py_False, borrowed) { }
|
||||
operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; }
|
||||
|
||||
private:
|
||||
@ -603,7 +628,7 @@ private:
|
||||
class int_ : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long)
|
||||
int_() : object(PyLong_FromLong(0), false) { }
|
||||
int_() : object(PyLong_FromLong(0), stolen) { }
|
||||
// Allow implicit conversion from C++ integral types:
|
||||
template <typename T,
|
||||
detail::enable_if_t<std::is_integral<T>::value, int> = 0>
|
||||
@ -643,10 +668,10 @@ class float_ : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float)
|
||||
// Allow implicit conversion from float/double:
|
||||
float_(float value) : object(PyFloat_FromDouble((double) value), false) {
|
||||
float_(float value) : object(PyFloat_FromDouble((double) value), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||
}
|
||||
float_(double value = .0) : object(PyFloat_FromDouble((double) value), false) {
|
||||
float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||
}
|
||||
operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
|
||||
@ -656,7 +681,8 @@ public:
|
||||
class weakref : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check)
|
||||
explicit weakref(handle obj, handle callback = handle()) : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), false) {
|
||||
explicit weakref(handle obj, handle callback = {})
|
||||
: object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate weak reference!");
|
||||
}
|
||||
};
|
||||
@ -681,9 +707,10 @@ public:
|
||||
class capsule : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
||||
capsule(PyObject *obj, bool borrowed) : object(obj, borrowed) { }
|
||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()")
|
||||
capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed) : object(ptr, stolen)) { }
|
||||
explicit capsule(const void *value, void (*destruct)(PyObject *) = nullptr)
|
||||
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), false) {
|
||||
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate capsule object!");
|
||||
}
|
||||
template <typename T> operator T *() const {
|
||||
@ -696,7 +723,7 @@ public:
|
||||
class tuple : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple)
|
||||
explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), false) {
|
||||
explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
|
||||
}
|
||||
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
|
||||
@ -706,7 +733,7 @@ public:
|
||||
class dict : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict)
|
||||
dict() : object(PyDict_New(), false) {
|
||||
dict() : object(PyDict_New(), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
|
||||
}
|
||||
template <typename... Args,
|
||||
@ -741,7 +768,7 @@ public:
|
||||
class list : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List)
|
||||
explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), false) {
|
||||
explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate list object!");
|
||||
}
|
||||
size_t size() const { return (size_t) PyList_Size(m_ptr); }
|
||||
@ -755,7 +782,7 @@ class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check)
|
||||
class set : public object {
|
||||
public:
|
||||
PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New)
|
||||
set() : object(PySet_New(nullptr), false) {
|
||||
set() : object(PySet_New(nullptr), stolen) {
|
||||
if (!m_ptr) pybind11_fail("Could not allocate set object!");
|
||||
}
|
||||
size_t size() const { return (size_t) PySet_Size(m_ptr); }
|
||||
@ -833,17 +860,31 @@ inline str repr(handle h) {
|
||||
Py_XDECREF(str_value); str_value = unicode;
|
||||
if (!str_value) throw error_already_set();
|
||||
#endif
|
||||
return {str_value, false};
|
||||
return reinterpret_steal<str>(str_value);
|
||||
}
|
||||
|
||||
NAMESPACE_BEGIN(detail)
|
||||
template <typename D> iterator object_api<D>::begin() const { return {PyObject_GetIter(derived().ptr()), false}; }
|
||||
template <typename D> iterator object_api<D>::end() const { return {nullptr, false}; }
|
||||
template <typename D> item_accessor object_api<D>::operator[](handle key) const { return {derived(), object(key, true)}; }
|
||||
template <typename D> item_accessor object_api<D>::operator[](const char *key) const { return {derived(), pybind11::str(key)}; }
|
||||
template <typename D> obj_attr_accessor object_api<D>::attr(handle key) const { return {derived(), object(key, true)}; }
|
||||
template <typename D> str_attr_accessor object_api<D>::attr(const char *key) const { return {derived(), key}; }
|
||||
template <typename D> args_proxy object_api<D>::operator*() const { return args_proxy(derived().ptr()); }
|
||||
template <typename D> iterator object_api<D>::begin() const {
|
||||
return reinterpret_steal<iterator>(PyObject_GetIter(derived().ptr()));
|
||||
}
|
||||
template <typename D> iterator object_api<D>::end() const {
|
||||
return {};
|
||||
}
|
||||
template <typename D> item_accessor object_api<D>::operator[](handle key) const {
|
||||
return {derived(), reinterpret_borrow<object>(key)};
|
||||
}
|
||||
template <typename D> item_accessor object_api<D>::operator[](const char *key) const {
|
||||
return {derived(), pybind11::str(key)};
|
||||
}
|
||||
template <typename D> obj_attr_accessor object_api<D>::attr(handle key) const {
|
||||
return {derived(), reinterpret_borrow<object>(key)};
|
||||
}
|
||||
template <typename D> str_attr_accessor object_api<D>::attr(const char *key) const {
|
||||
return {derived(), key};
|
||||
}
|
||||
template <typename D> args_proxy object_api<D>::operator*() const {
|
||||
return args_proxy(derived().ptr());
|
||||
}
|
||||
template <typename D> template <typename T> bool object_api<D>::contains(T &&key) const {
|
||||
return attr("__contains__")(std::forward<T>(key)).template cast<bool>();
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ template <typename Type, typename Key> struct set_caster {
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<pybind11::set>(src))
|
||||
return false;
|
||||
pybind11::set s(src, true);
|
||||
auto s = reinterpret_borrow<pybind11::set>(src);
|
||||
value.clear();
|
||||
key_conv conv;
|
||||
for (auto entry : s) {
|
||||
@ -61,7 +61,7 @@ template <typename Type, typename Key> struct set_caster {
|
||||
static handle cast(const type &src, return_value_policy policy, handle parent) {
|
||||
pybind11::set s;
|
||||
for (auto const &value: src) {
|
||||
object value_ = object(key_conv::cast(value, policy, parent), false);
|
||||
auto value_ = reinterpret_steal<object>(key_conv::cast(value, policy, parent));
|
||||
if (!value_ || !s.add(value_))
|
||||
return handle();
|
||||
}
|
||||
@ -79,7 +79,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<dict>(src))
|
||||
return false;
|
||||
dict d(src, true);
|
||||
auto d = reinterpret_borrow<dict>(src);
|
||||
key_conv kconv;
|
||||
value_conv vconv;
|
||||
value.clear();
|
||||
@ -95,8 +95,8 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
static handle cast(const type &src, return_value_policy policy, handle parent) {
|
||||
dict d;
|
||||
for (auto const &kv: src) {
|
||||
object key = object(key_conv::cast(kv.first, policy, parent), false);
|
||||
object value = object(value_conv::cast(kv.second, policy, parent), false);
|
||||
auto key = reinterpret_steal<object>(key_conv::cast(kv.first, policy, parent));
|
||||
auto value = reinterpret_steal<object>(value_conv::cast(kv.second, policy, parent));
|
||||
if (!key || !value)
|
||||
return handle();
|
||||
d[key] = value;
|
||||
@ -114,7 +114,7 @@ template <typename Type, typename Value> struct list_caster {
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src))
|
||||
return false;
|
||||
sequence s(src, true);
|
||||
auto s = reinterpret_borrow<sequence>(src);
|
||||
value_conv conv;
|
||||
value.clear();
|
||||
reserve_maybe(s, &value);
|
||||
@ -135,7 +135,7 @@ template <typename Type, typename Value> struct list_caster {
|
||||
list l(src.size());
|
||||
size_t index = 0;
|
||||
for (auto const &value: src) {
|
||||
object value_ = object(value_conv::cast(value, policy, parent), false);
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent));
|
||||
if (!value_)
|
||||
return handle();
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
@ -159,7 +159,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<list>(src))
|
||||
return false;
|
||||
list l(src, true);
|
||||
auto l = reinterpret_borrow<list>(src);
|
||||
if (l.size() != Size)
|
||||
return false;
|
||||
value_conv conv;
|
||||
@ -176,7 +176,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
|
||||
list l(Size);
|
||||
size_t index = 0;
|
||||
for (auto const &value: src) {
|
||||
object value_ = object(value_conv::cast(value, policy, parent), false);
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(value, policy, parent));
|
||||
if (!value_)
|
||||
return handle();
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
|
Loading…
Reference in New Issue
Block a user