Skip to content

Commit

Permalink
Use with_internals for all accesses to `internals.native_enum_type_…
Browse files Browse the repository at this point in the history
…map`
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Jul 30, 2024
1 parent 7d765a0 commit dcd1286
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 18 deletions.
27 changes: 13 additions & 14 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ class type_caster_enum_type {

template <typename SrcType>
static handle cast(SrcType &&src, return_value_policy, handle parent) {
auto const &natives = get_internals().native_enum_type_map;
auto found = natives.find(std::type_index(typeid(EnumType)));
if (found != natives.end()) {
return handle(found->second)(static_cast<Underlying>(src)).release();
handle native_enum
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
if (native_enum) {
return native_enum(static_cast<Underlying>(src)).release();
}
return type_caster_for_class_<EnumType>::cast(
std::forward<SrcType>(src),
Expand All @@ -101,10 +101,10 @@ class type_caster_enum_type {
}

bool load(handle src, bool convert) {
auto const &natives = get_internals().native_enum_type_map;
auto found = natives.find(std::type_index(typeid(EnumType)));
if (found != natives.end()) {
if (!isinstance(src, found->second)) {
handle native_enum
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
if (native_enum) {
if (!isinstance(src, native_enum)) {
return false;
}
type_caster<Underlying> underlying_caster;
Expand Down Expand Up @@ -180,12 +180,11 @@ struct type_caster_classh_enum_aware<

template <typename T, detail::enable_if_t<std::is_enum<T>::value, int> = 0>
bool isinstance_native_enum_impl(handle obj, const std::type_info &tp) {
auto const &natives = get_internals().native_enum_type_map;
auto found = natives.find(tp);
if (found == natives.end()) {
handle native_enum = global_internals_native_enum_type_map_get_item(tp);
if (!native_enum) {
return false;
}
return isinstance(obj, found->second);
return isinstance(obj, native_enum);
}

template <typename T, detail::enable_if_t<!std::is_enum<T>::value, int> = 0>
Expand Down Expand Up @@ -1351,8 +1350,8 @@ T cast(const handle &handle) {
"Unable to cast type to reference: value is local to type caster");
#ifndef NDEBUG
if (is_enum_cast && cast_is_temporary_value_reference<T>::value) {
auto const &natives = get_internals().native_enum_type_map;
if (natives.count(std::type_index(typeid(intrinsic_t<T>))) != 0) {
if (detail::global_internals_native_enum_type_map_contains(
std::type_index(typeid(intrinsic_t<T>)))) {
pybind11_fail("Unable to cast native enum type to reference");
}
}
Expand Down
26 changes: 25 additions & 1 deletion include/pybind11/detail/native_enum_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,30 @@ class native_enum_data {
list docs;
};

inline void global_internals_native_enum_type_map_set_item(const std::type_index &enum_type_index,
PyObject *py_enum) {
with_internals(
[&](internals &internals) { internals.native_enum_type_map[enum_type_index] = py_enum; });
}

inline handle
global_internals_native_enum_type_map_get_item(const std::type_index &enum_type_index) {
return with_internals([&](internals &internals) {
auto found = internals.native_enum_type_map.find(enum_type_index);
if (found != internals.native_enum_type_map.end()) {
return handle(found->second);
}
return handle();
});
}

inline bool
global_internals_native_enum_type_map_contains(const std::type_index &enum_type_index) {
return with_internals([&](internals &internals) {
return internals.native_enum_type_map.count(enum_type_index) != 0;
});
}

inline void native_enum_add_to_parent(const object &parent, const detail::native_enum_data &data) {
data.disarm_correct_use_check();
if (hasattr(parent, data.enum_name)) {
Expand Down Expand Up @@ -92,7 +116,7 @@ inline void native_enum_add_to_parent(const object &parent, const detail::native
for (auto doc : data.docs) {
py_enum[doc[int_(0)]].attr("__doc__") = doc[int_(1)];
}
get_internals().native_enum_type_map[data.enum_type_index] = py_enum.release().ptr();
global_internals_native_enum_type_map_set_item(data.enum_type_index, py_enum.release().ptr());
}

PYBIND11_NAMESPACE_END(detail)
Expand Down
2 changes: 1 addition & 1 deletion include/pybind11/native_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class native_enum : public detail::native_enum_data {
"pybind11::native_enum<...>(\"" + enum_name_encoded
+ "\") is already registered as a `pybind11::enum_` or `pybind11::class_`!");
}
if (detail::get_internals().native_enum_type_map.count(enum_type_index)) {
if (detail::global_internals_native_enum_type_map_contains(enum_type_index)) {
pybind11_fail("pybind11::native_enum<...>(\"" + enum_name_encoded
+ "\") is already registered!");
}
Expand Down
4 changes: 2 additions & 2 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -2614,8 +2614,8 @@ class enum_ : public class_<Type> {
enum_(const handle &scope, const char *name, const Extra &...extra)
: class_<Type>(scope, name, extra...), m_base(*this, scope) {
{
if (detail::get_internals().native_enum_type_map.count(std::type_index(typeid(Type)))
!= 0) {
if (detail::global_internals_native_enum_type_map_contains(
std::type_index(typeid(Type)))) {
pybind11_fail("pybind11::enum_ \"" + std::string(name)
+ "\" is already registered as a pybind11::native_enum!");
}
Expand Down

0 comments on commit dcd1286

Please sign in to comment.