Skip to content

Commit 18e8808

Browse files
committed
Add a __pybind11_enum__ capsule to native enums containing some information needed for interop with them, plus a destructor that unregisters the enum when it's destroyed
1 parent 1958388 commit 18e8808

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

include/pybind11/detail/internals.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,15 @@ struct type_info {
431431
bool module_local : 1;
432432
};
433433

434+
/// Information stored in a capsule on py::native_enum() types.
435+
struct native_enum_info {
436+
const std::type_info *cpptype;
437+
uint32_t size_bytes;
438+
bool is_signed;
439+
440+
static const char *attribute_name() { return "__pybind11_enum__"; }
441+
};
442+
434443
#define PYBIND11_ABI_TAG \
435444
"v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
436445
PYBIND11_COMPILER_TYPE_LEADING_UNDERSCORE PYBIND11_PLATFORM_ABI_ID

include/pybind11/detail/native_enum_data.h

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,25 @@ native_enum_missing_finalize_error_message(const std::string &enum_name_encoded)
2424

2525
class native_enum_data {
2626
public:
27-
native_enum_data(const object &parent_scope,
27+
native_enum_data(handle parent_scope,
2828
const char *enum_name,
2929
const char *native_type_name,
3030
const char *class_doc,
31-
const std::type_index &enum_type_index)
31+
const native_enum_info &enum_info_)
3232
: enum_name_encoded{enum_name}, native_type_name_encoded{native_type_name},
33-
enum_type_index{enum_type_index}, parent_scope(parent_scope), enum_name{enum_name},
33+
enum_type_index{*enum_info_.cpptype}, parent_scope(parent_scope), enum_name{enum_name},
3434
native_type_name{native_type_name}, class_doc(class_doc), export_values_flag{false},
35-
finalize_needed{false} {}
35+
finalize_needed{false} {
36+
enum_info = capsule(new native_enum_info{enum_info_},
37+
native_enum_info::attribute_name(),
38+
+[](void *enum_info_) {
39+
auto *info = (native_enum_info *) enum_info_;
40+
with_internals([&](internals &internals) {
41+
internals.native_enum_type_map.erase(*info->cpptype);
42+
});
43+
delete info;
44+
});
45+
}
3646

3747
void finalize();
3848

@@ -67,10 +77,11 @@ class native_enum_data {
6777
std::type_index enum_type_index;
6878

6979
private:
70-
object parent_scope;
80+
handle parent_scope;
7181
str enum_name;
7282
str native_type_name;
7383
std::string class_doc;
84+
capsule enum_info;
7485

7586
protected:
7687
list members;
@@ -81,12 +92,6 @@ class native_enum_data {
8192
bool finalize_needed : 1;
8293
};
8394

84-
inline void global_internals_native_enum_type_map_set_item(const std::type_index &enum_type_index,
85-
PyObject *py_enum) {
86-
with_internals(
87-
[&](internals &internals) { internals.native_enum_type_map[enum_type_index] = py_enum; });
88-
}
89-
9095
inline handle
9196
global_internals_native_enum_type_map_get_item(const std::type_index &enum_type_index) {
9297
return with_internals([&](internals &internals) {
@@ -202,7 +207,11 @@ inline void native_enum_data::finalize() {
202207
for (auto doc : member_docs) {
203208
py_enum[doc[int_(0)]].attr("__doc__") = doc[int_(1)];
204209
}
205-
global_internals_native_enum_type_map_set_item(enum_type_index, py_enum.release().ptr());
210+
211+
py_enum.attr(native_enum_info::attribute_name()) = enum_info;
212+
with_internals([&](internals &internals) {
213+
internals.native_enum_type_map[enum_type_index] = py_enum.ptr();
214+
});
206215
}
207216

208217
PYBIND11_NAMESPACE_END(detail)

0 commit comments

Comments
 (0)