Commit c7ac16bb by Dean Moldovan Committed by Wenzel Jakob

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.
parent e18bc02f
...@@ -182,7 +182,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> { ...@@ -182,7 +182,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
if (!src) if (!src)
return false; return false;
object obj(src, true); auto obj = reinterpret_borrow<object>(src);
object sparse_module = module::import("scipy.sparse"); object sparse_module = module::import("scipy.sparse");
object matrix_type = sparse_module.attr( object matrix_type = sparse_module.attr(
rowMajor ? "csr_matrix" : "csc_matrix"); rowMajor ? "csr_matrix" : "csc_matrix");
......
...@@ -31,7 +31,7 @@ enum eval_mode { ...@@ -31,7 +31,7 @@ enum eval_mode {
template <eval_mode mode = eval_expr> template <eval_mode mode = eval_expr>
object eval(str expr, object global = object(), object local = object()) { object eval(str expr, object global = object(), object local = object()) {
if (!global) { if (!global) {
global = object(PyEval_GetGlobals(), true); global = reinterpret_borrow<object>(PyEval_GetGlobals());
if (!global) if (!global)
global = dict(); global = dict();
} }
...@@ -50,17 +50,16 @@ object eval(str expr, object global = object(), object local = object()) { ...@@ -50,17 +50,16 @@ object eval(str expr, object global = object(), object local = object()) {
default: pybind11_fail("invalid evaluation mode"); 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) if (!result)
throw error_already_set(); throw error_already_set();
return result; return reinterpret_steal<object>(result);
} }
template <eval_mode mode = eval_statements> template <eval_mode mode = eval_statements>
object eval_file(str fname, object global = object(), object local = object()) { object eval_file(str fname, object global = object(), object local = object()) {
if (!global) { if (!global) {
global = object(PyEval_GetGlobals(), true); global = reinterpret_borrow<object>(PyEval_GetGlobals());
if (!global) if (!global)
global = dict(); global = dict();
} }
...@@ -83,9 +82,9 @@ object eval_file(str fname, object global = object(), object local = object()) { ...@@ -83,9 +82,9 @@ object eval_file(str fname, object global = object(), object local = object()) {
FILE *f = _Py_fopen(fname.ptr(), "r"); FILE *f = _Py_fopen(fname.ptr(), "r");
#else #else
/* No unicode support in open() :( */ /* 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 *>(fname_str.c_str()),
const_cast<char*>("r")), false); const_cast<char*>("r")));
FILE *f = nullptr; FILE *f = nullptr;
if (fobj) if (fobj)
f = PyFile_AsFile(fobj.ptr()); f = PyFile_AsFile(fobj.ptr());
...@@ -96,14 +95,11 @@ object eval_file(str fname, object global = object(), object local = object()) { ...@@ -96,14 +95,11 @@ object eval_file(str fname, object global = object(), object local = object()) {
pybind11_fail("File \"" + fname_str + "\" could not be opened!"); pybind11_fail("File \"" + fname_str + "\" could not be opened!");
} }
object result(PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
local.ptr(), closeFile), local.ptr(), closeFile);
false);
if (!result) if (!result)
throw error_already_set(); throw error_already_set();
return reinterpret_steal<object>(result);
return result;
} }
NAMESPACE_END(pybind11) NAMESPACE_END(pybind11)
...@@ -36,7 +36,7 @@ public: ...@@ -36,7 +36,7 @@ public:
captured variables), in which case the roundtrip can be avoided. captured variables), in which case the roundtrip can be avoided.
*/ */
if (PyCFunction_Check(src_.ptr())) { 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; auto rec = (function_record *) c;
using FunctionType = Return (*) (Args...); using FunctionType = Return (*) (Args...);
...@@ -47,7 +47,7 @@ public: ...@@ -47,7 +47,7 @@ public:
} }
} }
object src(src_, true); auto src = reinterpret_borrow<object>(src_);
value = [src](Args... args) -> Return { value = [src](Args... args) -> Return {
gil_scoped_acquire acq; gil_scoped_acquire acq;
object retval(src(std::move(args)...)); object retval(src(std::move(args)...));
......
...@@ -239,7 +239,7 @@ public: ...@@ -239,7 +239,7 @@ public:
PyObject *ptr = nullptr; PyObject *ptr = nullptr;
if (!detail::npy_api::get().PyArray_DescrConverter_(args.release().ptr(), &ptr) || !ptr) if (!detail::npy_api::get().PyArray_DescrConverter_(args.release().ptr(), &ptr) || !ptr)
throw error_already_set(); throw error_already_set();
return object(ptr, false); return reinterpret_steal<dtype>(ptr);
} }
/// Return dtype associated with a C++ type. /// Return dtype associated with a C++ type.
...@@ -266,7 +266,7 @@ private: ...@@ -266,7 +266,7 @@ private:
static object _dtype_from_pep3118() { static object _dtype_from_pep3118() {
static PyObject *obj = module::import("numpy.core._internal") static PyObject *obj = module::import("numpy.core._internal")
.attr("_dtype_from_pep3118").cast<object>().release().ptr(); .attr("_dtype_from_pep3118").cast<object>().release().ptr();
return object(obj, true); return reinterpret_borrow<object>(obj);
} }
dtype strip_padding() { dtype strip_padding() {
...@@ -279,7 +279,7 @@ private: ...@@ -279,7 +279,7 @@ private:
std::vector<field_descr> field_descriptors; std::vector<field_descr> field_descriptors;
for (auto field : attr("fields").attr("items")()) { 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 name = spec[0].cast<pybind11::str>();
auto format = spec[1].cast<tuple>()[0].cast<dtype>(); auto format = spec[1].cast<tuple>()[0].cast<dtype>();
auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>(); auto offset = spec[1].cast<tuple>()[1].cast<pybind11::int_>();
...@@ -326,22 +326,22 @@ public: ...@@ -326,22 +326,22 @@ public:
if (base && ptr) { if (base && ptr) {
if (isinstance<array>(base)) if (isinstance<array>(base))
/* Copy flags from base (except baseship bit) */ /* 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 else
/* Writable by default, easy to downgrade later on if needed */ /* Writable by default, easy to downgrade later on if needed */
flags = detail::npy_api::NPY_ARRAY_WRITEABLE_; 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(), 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) if (!tmp)
pybind11_fail("NumPy: unable to create array!"); pybind11_fail("NumPy: unable to create array!");
if (ptr) { if (ptr) {
if (base) { if (base) {
PyArray_GET_(tmp.ptr(), base) = base.inc_ref().ptr(); PyArray_GET_(tmp.ptr(), base) = base.inc_ref().ptr();
} else { } 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(); m_ptr = tmp.release().ptr();
...@@ -374,7 +374,7 @@ public: ...@@ -374,7 +374,7 @@ public:
/// Array descriptor (dtype) /// Array descriptor (dtype)
pybind11::dtype dtype() const { 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 /// Total number of elements
...@@ -399,7 +399,7 @@ public: ...@@ -399,7 +399,7 @@ public:
/// Base object /// Base object
object base() const { object base() const {
return object(PyArray_GET_(m_ptr, base), true); return reinterpret_borrow<object>(PyArray_GET_(m_ptr, base));
} }
/// Dimensions of the array /// Dimensions of the array
...@@ -474,14 +474,14 @@ public: ...@@ -474,14 +474,14 @@ public:
/// Return a new view with all of the dimensions of length 1 removed /// Return a new view with all of the dimensions of length 1 removed
array squeeze() { array squeeze() {
auto& api = detail::npy_api::get(); 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 /// Ensure that the argument is a NumPy array
static array ensure(object input, int ExtraFlags = 0) { static array ensure(object input, int ExtraFlags = 0) {
auto& api = detail::npy_api::get(); auto& api = detail::npy_api::get();
return array(api.PyArray_FromAny_( return reinterpret_steal<array>(api.PyArray_FromAny_(
input.release().ptr(), nullptr, 0, 0, detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr), false); input.release().ptr(), nullptr, 0, 0, detail::npy_api::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr));
} }
protected: protected:
...@@ -542,7 +542,7 @@ template <typename T, int ExtraFlags = array::forcecast> class array_t : public ...@@ -542,7 +542,7 @@ template <typename T, int ExtraFlags = array::forcecast> class array_t : public
public: public:
array_t() : array() { } 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); } array_t(const object &o) : array(o) { m_ptr = ensure_(m_ptr); }
...@@ -668,7 +668,7 @@ public: ...@@ -668,7 +668,7 @@ public:
enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned<T>::value ? 1 : 0)] }; enum { value = values[detail::log2(sizeof(T)) * 2 + (std::is_unsigned<T>::value ? 1 : 0)] };
static pybind11::dtype dtype() { static pybind11::dtype dtype() {
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) if (auto ptr = npy_api::get().PyArray_DescrFromType_(value))
return object(ptr, true); return reinterpret_borrow<pybind11::dtype>(ptr);
pybind11_fail("Unsupported buffer format!"); pybind11_fail("Unsupported buffer format!");
} }
template <typename T2 = T, enable_if_t<std::is_signed<T2>::value, int> = 0> 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< ...@@ -683,7 +683,7 @@ template <typename T> constexpr const int npy_format_descriptor<
enum { value = npy_api::NumPyName }; \ enum { value = npy_api::NumPyName }; \
static pybind11::dtype dtype() { \ static pybind11::dtype dtype() { \
if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) \ if (auto ptr = npy_api::get().PyArray_DescrFromType_(value)) \
return object(ptr, true); \ return reinterpret_borrow<pybind11::dtype>(ptr); \
pybind11_fail("Unsupported buffer format!"); \ pybind11_fail("Unsupported buffer format!"); \
} \ } \
static PYBIND11_DESCR name() { return _(Name); } } static PYBIND11_DESCR name() { return _(Name); } }
...@@ -778,7 +778,7 @@ struct npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>> { ...@@ -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_DESCR name() { return _("struct"); }
static pybind11::dtype dtype() { static pybind11::dtype dtype() {
return object(dtype_ptr(), true); return reinterpret_borrow<pybind11::dtype>(dtype_ptr());
} }
static std::string format() { static std::string format() {
...@@ -801,7 +801,7 @@ private: ...@@ -801,7 +801,7 @@ private:
auto& api = npy_api::get(); auto& api = npy_api::get();
if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_)) if (!PyObject_TypeCheck(obj, api.PyVoidArrType_Type_))
return false; 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())) { if (api.PyArray_EquivTypes_(dtype_ptr(), descr.ptr())) {
value = ((PyVoidScalarObject_Proxy *) obj)->obval; value = ((PyVoidScalarObject_Proxy *) obj)->obval;
return true; return true;
......
...@@ -256,7 +256,7 @@ protected: ...@@ -256,7 +256,7 @@ protected:
detail::function_record *chain = nullptr, *chain_start = rec; detail::function_record *chain = nullptr, *chain_start = rec;
if (rec->sibling) { if (rec->sibling) {
if (PyCFunction_Check(rec->sibling.ptr())) { 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; chain = (detail::function_record *) rec_capsule;
/* Never append a method to an overload chain of a parent class; /* Never append a method to an overload chain of a parent class;
instead, hide the parent's overloads in this case */ instead, hide the parent's overloads in this case */
...@@ -382,7 +382,7 @@ protected: ...@@ -382,7 +382,7 @@ protected:
result = PYBIND11_TRY_NEXT_OVERLOAD; result = PYBIND11_TRY_NEXT_OVERLOAD;
try { try {
for (; it != nullptr; it = it->next) { for (; it != nullptr; it = it->next) {
tuple args_(args, true); auto args_ = reinterpret_borrow<tuple>(args);
size_t kwargs_consumed = 0; size_t kwargs_consumed = 0;
/* For each overload: /* For each overload:
...@@ -502,7 +502,7 @@ protected: ...@@ -502,7 +502,7 @@ protected:
msg += "\n"; msg += "\n";
} }
msg += "\nInvoked with: "; 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) { for (size_t ti = overloads->is_constructor ? 1 : 0; ti < args_.size(); ++ti) {
msg += static_cast<std::string>(pybind11::str(args_[ti])); msg += static_cast<std::string>(pybind11::str(args_[ti]));
if ((ti + 1) != args_.size() ) if ((ti + 1) != args_.size() )
...@@ -565,7 +565,7 @@ public: ...@@ -565,7 +565,7 @@ public:
module def_submodule(const char *name, const char *doc = nullptr) { module def_submodule(const char *name, const char *doc = nullptr) {
std::string full_name = std::string(PyModule_GetName(m_ptr)) std::string full_name = std::string(PyModule_GetName(m_ptr))
+ std::string(".") + std::string(name); + 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()) if (doc && options::show_user_defined_docstrings())
result.attr("__doc__") = pybind11::str(doc); result.attr("__doc__") = pybind11::str(doc);
attr(name) = result; attr(name) = result;
...@@ -576,7 +576,7 @@ public: ...@@ -576,7 +576,7 @@ public:
PyObject *obj = PyImport_ImportModule(name); PyObject *obj = PyImport_ImportModule(name);
if (!obj) if (!obj)
throw import_error("Module \"" + std::string(name) + "\" not found!"); 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 // Adds an object to the module using the given name. Throws if an object with the given name
...@@ -636,7 +636,7 @@ protected: ...@@ -636,7 +636,7 @@ protected:
pybind11_fail("generic_type: type \"" + std::string(rec->name) + pybind11_fail("generic_type: type \"" + std::string(rec->name) +
"\" is already registered!"); "\" is already registered!");
object name(PYBIND11_FROM_STRING(rec->name), false); auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec->name));
object scope_module; object scope_module;
if (rec->scope) { if (rec->scope) {
if (hasattr(rec->scope, rec->name)) if (hasattr(rec->scope, rec->name))
...@@ -657,8 +657,8 @@ protected: ...@@ -657,8 +657,8 @@ protected:
scope_qualname = rec->scope.attr("__qualname__"); scope_qualname = rec->scope.attr("__qualname__");
object ht_qualname; object ht_qualname;
if (scope_qualname) { if (scope_qualname) {
ht_qualname = object(PyUnicode_FromFormat( ht_qualname = reinterpret_steal<object>(PyUnicode_FromFormat(
"%U.%U", scope_qualname.ptr(), name.ptr()), false); "%U.%U", scope_qualname.ptr(), name.ptr()));
} else { } else {
ht_qualname = name; ht_qualname = name;
} }
...@@ -684,7 +684,7 @@ protected: ...@@ -684,7 +684,7 @@ protected:
garbage collector (the GC will call type_traverse(), which will in garbage collector (the GC will call type_traverse(), which will in
turn find the newly constructed type in an invalid state) */ 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(); auto type = (PyHeapTypeObject*) type_holder.ptr();
if (!type_holder || !name) if (!type_holder || !name)
...@@ -768,7 +768,7 @@ protected: ...@@ -768,7 +768,7 @@ protected:
/// Helper function which tags all parents of a type using mult. inheritance /// Helper function which tags all parents of a type using mult. inheritance
void mark_parents_nonsimple(PyTypeObject *value) { void mark_parents_nonsimple(PyTypeObject *value) {
tuple t(value->tp_bases, true); auto t = reinterpret_borrow<tuple>(value->tp_bases);
for (handle h : t) { for (handle h : t) {
auto tinfo2 = get_type_info((PyTypeObject *) h.ptr()); auto tinfo2 = get_type_info((PyTypeObject *) h.ptr());
if (tinfo2) if (tinfo2)
...@@ -785,10 +785,10 @@ protected: ...@@ -785,10 +785,10 @@ protected:
if (ob_type == &PyType_Type) { if (ob_type == &PyType_Type) {
std::string name_ = std::string(ht_type.tp_name) + "__Meta"; std::string name_ = std::string(ht_type.tp_name) + "__Meta";
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 #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 #endif
object name(PYBIND11_FROM_STRING(name_.c_str()), false); auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(name_.c_str()));
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false); auto type_holder = reinterpret_steal<object>(PyType_Type.tp_alloc(&PyType_Type, 0));
if (!type_holder || !name) if (!type_holder || !name)
pybind11_fail("generic_type::metaclass(): unable to create type object!"); pybind11_fail("generic_type::metaclass(): unable to create type object!");
...@@ -936,7 +936,7 @@ public: ...@@ -936,7 +936,7 @@ public:
static_assert(detail::all_of_t<is_valid_class_option, options...>::value, static_assert(detail::all_of_t<is_valid_class_option, options...>::value,
"Unknown/invalid class_ template parameters provided"); "Unknown/invalid class_ template parameters provided");
PYBIND11_OBJECT(class_, detail::generic_type, PyType_Check) PYBIND11_OBJECT(class_, generic_type, PyType_Check)
template <typename... Extra> template <typename... Extra>
class_(handle scope, const char *name, const Extra &... extra) { class_(handle scope, const char *name, const Extra &... extra) {
...@@ -1117,9 +1117,9 @@ public: ...@@ -1117,9 +1117,9 @@ public:
} }
} }
pybind11::str doc_obj = pybind11::str((rec_fget->doc && pybind11::options::show_user_defined_docstrings()) ? rec_fget->doc : ""); 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, 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_) if (rec_fget->class_)
attr(name) = property; attr(name) = property;
else else
...@@ -1178,8 +1178,8 @@ private: ...@@ -1178,8 +1178,8 @@ private:
static detail::function_record *get_function_record(handle h) { static detail::function_record *get_function_record(handle h) {
h = detail::get_function(h); h = detail::get_function(h);
return h ? (detail::function_record *) capsule( return h ? (detail::function_record *) reinterpret_borrow<capsule>(PyCFunction_GetSelf(h.ptr()))
PyCFunction_GetSelf(h.ptr()), true) : nullptr; : nullptr;
} }
}; };
......
...@@ -47,7 +47,7 @@ template <typename Type, typename Key> struct set_caster { ...@@ -47,7 +47,7 @@ template <typename Type, typename Key> struct set_caster {
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<pybind11::set>(src)) if (!isinstance<pybind11::set>(src))
return false; return false;
pybind11::set s(src, true); auto s = reinterpret_borrow<pybind11::set>(src);
value.clear(); value.clear();
key_conv conv; key_conv conv;
for (auto entry : s) { for (auto entry : s) {
...@@ -61,7 +61,7 @@ template <typename Type, typename Key> struct set_caster { ...@@ -61,7 +61,7 @@ template <typename Type, typename Key> struct set_caster {
static handle cast(const type &src, return_value_policy policy, handle parent) { static handle cast(const type &src, return_value_policy policy, handle parent) {
pybind11::set s; pybind11::set s;
for (auto const &value: src) { 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_)) if (!value_ || !s.add(value_))
return handle(); return handle();
} }
...@@ -79,7 +79,7 @@ template <typename Type, typename Key, typename Value> struct map_caster { ...@@ -79,7 +79,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<dict>(src)) if (!isinstance<dict>(src))
return false; return false;
dict d(src, true); auto d = reinterpret_borrow<dict>(src);
key_conv kconv; key_conv kconv;
value_conv vconv; value_conv vconv;
value.clear(); value.clear();
...@@ -95,8 +95,8 @@ template <typename Type, typename Key, typename Value> struct map_caster { ...@@ -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) { static handle cast(const type &src, return_value_policy policy, handle parent) {
dict d; dict d;
for (auto const &kv: src) { for (auto const &kv: src) {
object key = object(key_conv::cast(kv.first, policy, parent), false); auto key = reinterpret_steal<object>(key_conv::cast(kv.first, policy, parent));
object value = object(value_conv::cast(kv.second, policy, parent), false); auto value = reinterpret_steal<object>(value_conv::cast(kv.second, policy, parent));
if (!key || !value) if (!key || !value)
return handle(); return handle();
d[key] = value; d[key] = value;
...@@ -114,7 +114,7 @@ template <typename Type, typename Value> struct list_caster { ...@@ -114,7 +114,7 @@ template <typename Type, typename Value> struct list_caster {
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<sequence>(src)) if (!isinstance<sequence>(src))
return false; return false;
sequence s(src, true); auto s = reinterpret_borrow<sequence>(src);
value_conv conv; value_conv conv;
value.clear(); value.clear();
reserve_maybe(s, &value); reserve_maybe(s, &value);
...@@ -135,7 +135,7 @@ template <typename Type, typename Value> struct list_caster { ...@@ -135,7 +135,7 @@ template <typename Type, typename Value> struct list_caster {
list l(src.size()); list l(src.size());
size_t index = 0; size_t index = 0;
for (auto const &value: src) { 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_) if (!value_)
return handle(); return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference 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>> ...@@ -159,7 +159,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!isinstance<list>(src)) if (!isinstance<list>(src))
return false; return false;
list l(src, true); auto l = reinterpret_borrow<list>(src);
if (l.size() != Size) if (l.size() != Size)
return false; return false;
value_conv conv; value_conv conv;
...@@ -176,7 +176,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>> ...@@ -176,7 +176,7 @@ template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
list l(Size); list l(Size);
size_t index = 0; size_t index = 0;
for (auto const &value: src) { 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_) if (!value_)
return handle(); return handle();
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment