Skip to content

Commit 598ebcd

Browse files
committed
refactor: using py::type as class
1 parent f3aec83 commit 598ebcd

File tree

4 files changed

+38
-16
lines changed

4 files changed

+38
-16
lines changed

docs/advanced/classes.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ crucial that instances are deallocated on the C++ side to avoid memory leaks.
562562

563563
Destructors that call Python
564564
============================
565-
565+
earch);45M
566566
If a Python function is invoked from a C++ destructor, an exception may be thrown
567567
of type :class:`error_already_set`. If this error is thrown out of a class destructor,
568568
``std::terminate()`` will be called, terminating the process. Class destructors
@@ -1232,3 +1232,17 @@ appropriate derived-class pointer (e.g. using
12321232
more complete example, including a demonstration of how to provide
12331233
automatic downcasting for an entire class hierarchy without
12341234
writing one get() function for each class.
1235+
1236+
Accessing the type object
1237+
=========================
1238+
1239+
You can get the type object from a C++ class that has already been registered using:
1240+
1241+
.. code-block:: python
1242+
1243+
auto T_py = py::type::of<T>();
1244+
1245+
You can directly use ``py::type(ob)`` to get the type object from any python
1246+
object, just like ``type(ob)`` in Python.
1247+
1248+
.. versionadded:: 2.6

include/pybind11/cast.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,25 +2204,16 @@ object object_api<Derived>::call(Args &&...args) const {
22042204
PYBIND11_NAMESPACE_END(detail)
22052205

22062206

2207-
/** \ingroup python_builtins
2208-
\rst
2209-
Return the registered type object for a C++ class, given as a template parameter.
2210-
py::type<T>() returns the Python type object previously registered for T.
2211-
\endrst */
22122207
template<typename T>
2213-
handle type() {
2214-
static_assert(
2208+
type type::of() {
2209+
static_assert(
22152210
std::is_base_of<detail::type_caster_generic, detail::make_caster<T>>::value,
22162211
"This currently only works for registered C++ types. The type here is most likely type converted (using type_caster)."
22172212
);
22182213

2219-
return detail::get_type_handle(typeid(T), true);
2214+
return type((PyTypeObject*) detail::get_type_handle(typeid(T), true).ptr());
22202215
}
22212216

2222-
inline handle type(handle h) {
2223-
PyObject* obj = (PyObject *) Py_TYPE(h.ptr());
2224-
return handle(obj);
2225-
}
22262217

22272218
#define PYBIND11_MAKE_OPAQUE(...) \
22282219
namespace pybind11 { namespace detail { \

include/pybind11/pytypes.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1919
/* A few forward declarations */
2020
class handle; class object;
2121
class str; class iterator;
22+
class type;
2223
struct arg; struct arg_v;
2324

2425
PYBIND11_NAMESPACE_BEGIN(detail)
@@ -890,6 +891,22 @@ class iterator : public object {
890891
object value = {};
891892
};
892893

894+
class type : public handle {
895+
public:
896+
// Explicit omitted here since PyTypeObject required (rather than just PyObject)
897+
type(PyTypeObject* type_ptr) : handle((PyObject*) type_ptr) {}
898+
899+
/// Giving a handle/object gets the type from it
900+
explicit type(const handle& h) : handle((PyObject *) Py_TYPE(h.ptr())) {}
901+
902+
/// Convert C++ type to py::type if prevously registered. Does not convert standard types, like int, float. etc. yet.
903+
template<typename T>
904+
static type of();
905+
906+
/// Custom check function that also ensures this is a type
907+
bool check() const { return ptr() != nullptr && PyType_Check(ptr());}
908+
};
909+
893910
class iterable : public object {
894911
public:
895912
PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check)

tests/test_class.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ TEST_SUBMODULE(class_, m) {
140140
m.def("check_type", [](int category) {
141141
// Currently not supported (via a fail at compile time)
142142
// if (category == 2)
143-
// return py::type<int>();
143+
// return py::type::of<int>();
144144
if (category == 1)
145-
return py::type<DerivedClass1>();
145+
return py::type::of<DerivedClass1>();
146146
else
147-
return py::type<Invalid>();
147+
return py::type::of<Invalid>();
148148
});
149149

150150
m.def("compute_type", [](py::handle h) {

0 commit comments

Comments
 (0)