mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-23 05:35:13 +00:00
Move common object functions into object_api mixin
This commit is contained in:
parent
2d9220f09d
commit
37e22e436e
@ -276,7 +276,7 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
|||||||
|
|
||||||
/// Process a parent class attribute
|
/// Process a parent class attribute
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct process_attribute<T, enable_if_t<std::is_base_of<handle, T>::value>> : process_attribute_default<handle> {
|
struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> {
|
||||||
static void init(const handle &h, type_record *r) { r->bases.append(h); }
|
static void init(const handle &h, type_record *r) { r->bases.append(h); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -908,7 +908,7 @@ template <> struct handle_type_name<args> { static PYBIND11_DESCR name() { retur
|
|||||||
template <> struct handle_type_name<kwargs> { static PYBIND11_DESCR name() { return _("**kwargs"); } };
|
template <> struct handle_type_name<kwargs> { static PYBIND11_DESCR name() { return _("**kwargs"); } };
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
struct type_caster<type, enable_if_t<std::is_base_of<handle, type>::value>> {
|
struct type_caster<type, enable_if_t<is_pyobject<type>::value>> {
|
||||||
public:
|
public:
|
||||||
template <typename T = type, enable_if_t<!std::is_base_of<object, T>::value, int> = 0>
|
template <typename T = type, enable_if_t<!std::is_base_of<object, T>::value, int> = 0>
|
||||||
bool load(handle src, bool /* convert */) { value = type(src); return value.check(); }
|
bool load(handle src, bool /* convert */) { value = type(src); return value.check(); }
|
||||||
@ -1296,18 +1296,20 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
|
|||||||
return { std::forward<Args>(args)... };
|
return { std::forward<Args>(args)... };
|
||||||
}
|
}
|
||||||
|
|
||||||
NAMESPACE_END(detail)
|
template <typename Derived>
|
||||||
|
|
||||||
template <return_value_policy policy, typename... Args>
|
template <return_value_policy policy, typename... Args>
|
||||||
object handle::operator()(Args &&...args) const {
|
object object_api<Derived>::operator()(Args &&...args) const {
|
||||||
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(m_ptr);
|
return detail::collect_arguments<policy>(std::forward<Args>(args)...).call(derived().ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <return_value_policy policy,
|
template <typename Derived>
|
||||||
typename... Args> object handle::call(Args &&... args) const {
|
template <return_value_policy policy, typename... Args>
|
||||||
|
object object_api<Derived>::call(Args &&...args) const {
|
||||||
return operator()<policy>(std::forward<Args>(args)...);
|
return operator()<policy>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NAMESPACE_END(detail)
|
||||||
|
|
||||||
#define PYBIND11_MAKE_OPAQUE(Type) \
|
#define PYBIND11_MAKE_OPAQUE(Type) \
|
||||||
namespace pybind11 { namespace detail { \
|
namespace pybind11 { namespace detail { \
|
||||||
template<> class type_caster<Type> : public type_caster_base<Type> { }; \
|
template<> class type_caster<Type> : public type_caster_base<Type> { }; \
|
||||||
|
@ -16,50 +16,72 @@
|
|||||||
NAMESPACE_BEGIN(pybind11)
|
NAMESPACE_BEGIN(pybind11)
|
||||||
|
|
||||||
/* A few forward declarations */
|
/* A few forward declarations */
|
||||||
class object; class str; class iterator;
|
class handle; class object;
|
||||||
|
class str; class iterator;
|
||||||
struct arg; struct arg_v;
|
struct arg; struct arg_v;
|
||||||
namespace detail { class accessor; class args_proxy; class kwargs_proxy; }
|
|
||||||
|
NAMESPACE_BEGIN(detail)
|
||||||
|
class accessor; class args_proxy;
|
||||||
|
|
||||||
|
/// Tag and check to identify a class which implements the Python object API
|
||||||
|
class pyobject_tag { };
|
||||||
|
template <typename T> using is_pyobject = std::is_base_of<pyobject_tag, T>;
|
||||||
|
|
||||||
|
/// Mixin which adds common functions to handle, object and various accessors.
|
||||||
|
/// The only requirement for `Derived` is to implement `PyObject *Derived::ptr() const`.
|
||||||
|
template <typename Derived>
|
||||||
|
class object_api : public pyobject_tag {
|
||||||
|
const Derived &derived() const { return static_cast<const Derived &>(*this); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator begin() const;
|
||||||
|
iterator end() const;
|
||||||
|
accessor operator[](handle key) const;
|
||||||
|
accessor operator[](const char *key) const;
|
||||||
|
accessor attr(handle key) const;
|
||||||
|
accessor attr(const char *key) const;
|
||||||
|
args_proxy operator*() const;
|
||||||
|
|
||||||
|
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
|
||||||
|
object operator()(Args &&...args) const;
|
||||||
|
template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args>
|
||||||
|
PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)")
|
||||||
|
object call(Args&&... args) const;
|
||||||
|
|
||||||
|
bool is_none() const { return derived().ptr() == Py_None; }
|
||||||
|
pybind11::str str() const;
|
||||||
|
pybind11::str repr() const;
|
||||||
|
|
||||||
|
int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); }
|
||||||
|
handle get_type() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
NAMESPACE_END(detail)
|
||||||
|
|
||||||
/// Holds a reference to a Python object (no reference counting)
|
/// Holds a reference to a Python object (no reference counting)
|
||||||
class handle {
|
class handle : public detail::object_api<handle> {
|
||||||
public:
|
public:
|
||||||
handle() : m_ptr(nullptr) { }
|
handle() = default;
|
||||||
handle(const handle &other) : m_ptr(other.m_ptr) { }
|
|
||||||
handle(PyObject *ptr) : m_ptr(ptr) { }
|
handle(PyObject *ptr) : m_ptr(ptr) { }
|
||||||
|
|
||||||
PyObject *ptr() const { return m_ptr; }
|
PyObject *ptr() const { return m_ptr; }
|
||||||
PyObject *&ptr() { return m_ptr; }
|
PyObject *&ptr() { return m_ptr; }
|
||||||
const handle& inc_ref() const { Py_XINCREF(m_ptr); return *this; }
|
const handle& inc_ref() const { Py_XINCREF(m_ptr); return *this; }
|
||||||
const handle& dec_ref() const { Py_XDECREF(m_ptr); return *this; }
|
const handle& dec_ref() const { Py_XDECREF(m_ptr); return *this; }
|
||||||
int ref_count() const { return (int) Py_REFCNT(m_ptr); }
|
|
||||||
handle get_type() const { return handle((PyObject *) Py_TYPE(m_ptr)); }
|
|
||||||
inline iterator begin() const;
|
|
||||||
inline iterator end() const;
|
|
||||||
inline detail::accessor operator[](handle key) const;
|
|
||||||
inline detail::accessor operator[](const char *key) const;
|
|
||||||
inline detail::accessor attr(handle key) const;
|
|
||||||
inline detail::accessor attr(const char *key) const;
|
|
||||||
inline pybind11::str str() const;
|
|
||||||
inline pybind11::str repr() const;
|
|
||||||
bool is_none() const { return m_ptr == Py_None; }
|
|
||||||
template <typename T> T cast() const;
|
template <typename T> T cast() const;
|
||||||
template <return_value_policy policy = return_value_policy::automatic_reference, typename ... Args>
|
|
||||||
PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)")
|
|
||||||
object call(Args&&... args) const;
|
|
||||||
template <return_value_policy policy = return_value_policy::automatic_reference, typename ... Args>
|
|
||||||
object operator()(Args&&... args) const;
|
|
||||||
operator bool() const { return m_ptr != nullptr; }
|
operator bool() const { return m_ptr != nullptr; }
|
||||||
bool operator==(const handle &h) const { return m_ptr == h.m_ptr; }
|
bool operator==(const handle &h) const { return m_ptr == h.m_ptr; }
|
||||||
bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; }
|
bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; }
|
||||||
bool check() const { return m_ptr != nullptr; }
|
bool check() const { return m_ptr != nullptr; }
|
||||||
inline detail::args_proxy operator*() const;
|
|
||||||
protected:
|
protected:
|
||||||
PyObject *m_ptr;
|
PyObject *m_ptr = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Holds a reference to a Python object (with reference counting)
|
/// Holds a reference to a Python object (with reference counting)
|
||||||
class object : public handle {
|
class object : public handle {
|
||||||
public:
|
public:
|
||||||
object() { }
|
object() = default;
|
||||||
object(const object &o) : handle(o) { inc_ref(); }
|
object(const object &o) : handle(o) { inc_ref(); }
|
||||||
object(const handle &h, bool borrowed) : handle(h) { if (borrowed) 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(PyObject *ptr, bool borrowed) : handle(ptr) { if (borrowed) inc_ref(); }
|
||||||
@ -347,14 +369,6 @@ public:
|
|||||||
PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check)
|
PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(*this, key, false); }
|
|
||||||
inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(*this, key, false); }
|
|
||||||
inline detail::accessor handle::attr(handle key) const { return detail::accessor(*this, key, true); }
|
|
||||||
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(*this, key, true); }
|
|
||||||
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr()), false); }
|
|
||||||
inline iterator handle::end() const { return iterator(nullptr, false); }
|
|
||||||
inline detail::args_proxy handle::operator*() const { return detail::args_proxy(*this); }
|
|
||||||
|
|
||||||
class bytes;
|
class bytes;
|
||||||
|
|
||||||
class str : public object {
|
class str : public object {
|
||||||
@ -400,24 +414,6 @@ inline namespace literals {
|
|||||||
inline str operator"" _s(const char *s, size_t size) { return {s, size}; }
|
inline str operator"" _s(const char *s, size_t size) { return {s, size}; }
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pybind11::str handle::str() const {
|
|
||||||
PyObject *strValue = PyObject_Str(m_ptr);
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
|
||||||
PyObject *unicode = PyUnicode_FromEncodedObject(strValue, "utf-8", nullptr);
|
|
||||||
Py_XDECREF(strValue); strValue = unicode;
|
|
||||||
#endif
|
|
||||||
return pybind11::str(strValue, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline pybind11::str handle::repr() const {
|
|
||||||
PyObject *strValue = PyObject_Repr(m_ptr);
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
|
||||||
PyObject *unicode = PyUnicode_FromEncodedObject(strValue, "utf-8", nullptr);
|
|
||||||
Py_XDECREF(strValue); strValue = unicode;
|
|
||||||
#endif
|
|
||||||
return pybind11::str(strValue, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
class bytes : public object {
|
class bytes : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(bytes, object, PYBIND11_BYTES_CHECK)
|
PYBIND11_OBJECT_DEFAULT(bytes, object, PYBIND11_BYTES_CHECK)
|
||||||
@ -691,4 +687,37 @@ inline size_t len(handle h) {
|
|||||||
return (size_t) result;
|
return (size_t) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> accessor object_api<D>::operator[](handle key) const { return {derived(), key, false}; }
|
||||||
|
template <typename D> accessor object_api<D>::operator[](const char *key) const { return {derived(), key, false}; }
|
||||||
|
template <typename D> accessor object_api<D>::attr(handle key) const { return {derived(), key, true}; }
|
||||||
|
template <typename D> accessor object_api<D>::attr(const char *key) const { return {derived(), key, true}; }
|
||||||
|
template <typename D> args_proxy object_api<D>::operator*() const { return {derived().ptr()}; }
|
||||||
|
|
||||||
|
template <typename D>
|
||||||
|
pybind11::str object_api<D>::str() const {
|
||||||
|
PyObject *str_value = PyObject_Str(derived().ptr());
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
|
||||||
|
Py_XDECREF(str_value); str_value = unicode;
|
||||||
|
#endif
|
||||||
|
return {str_value, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename D>
|
||||||
|
pybind11::str object_api<D>::repr() const {
|
||||||
|
PyObject *str_value = PyObject_Repr(derived().ptr());
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
|
||||||
|
Py_XDECREF(str_value); str_value = unicode;
|
||||||
|
#endif
|
||||||
|
return {str_value, false};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename D>
|
||||||
|
handle object_api<D>::get_type() const { return (PyObject *) Py_TYPE(derived().ptr()); }
|
||||||
|
|
||||||
|
NAMESPACE_END(detail)
|
||||||
NAMESPACE_END(pybind11)
|
NAMESPACE_END(pybind11)
|
||||||
|
Loading…
Reference in New Issue
Block a user