From b6cf75d66a72ceb395a9e198d2be696a783b3175 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 29 Jan 2016 11:39:32 +0100 Subject: [PATCH] address issue with std::type_info across module boundaries (fixes #86) --- include/pybind11/cast.h | 17 +++-------------- include/pybind11/common.h | 7 ++++--- include/pybind11/pybind11.h | 10 +++++----- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 909ce141..2dfcc771 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -59,20 +59,9 @@ PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) { PYBIND11_NOINLINE inline detail::type_info *get_type_info(const std::type_info &tp) { auto &types = get_internals().registered_types_cpp; - auto it = types.find(&tp); - if (it != types.end()) { + auto it = types.find(std::type_index(tp)); + if (it != types.end()) return (detail::type_info *) it->second; - } else { - /* Unknown type?! Since std::type_info* often varies across - module boundaries, the following does an explicit check */ - for (auto const &type : types) { - auto *first = (const std::type_info *) type.first; - if (strcmp(first->name(), tp.name()) == 0) { - types[&tp] = type.second; - return (detail::type_info *) type.second; - } - } - } return nullptr; } @@ -144,7 +133,7 @@ public: if (it_instance != internals.registered_instances.end() && !dont_cache) return handle((PyObject *) it_instance->second).inc_ref(); - auto it = internals.registered_types_cpp.find(type_info); + auto it = internals.registered_types_cpp.find(std::type_index(*type_info)); if (it == internals.registered_types_cpp.end()) { std::string tname = type_info->name(); detail::clean_type_id(tname); diff --git a/include/pybind11/common.h b/include/pybind11/common.h index 97343469..6d06c9dd 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -71,6 +71,7 @@ #include #include #include +#include #if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions #define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr) @@ -216,9 +217,9 @@ struct overload_hash { /// Internal data struture used to track registered instances and types struct internals { - std::unordered_map registered_types_cpp; // std::type_info* -> type_info - std::unordered_map registered_types_py; // PyTypeObject* -> type_info - std::unordered_map registered_instances; // void * -> PyObject* + std::unordered_map registered_types_cpp; // std::type_index -> type_info + std::unordered_map registered_types_py; // PyTypeObject* -> type_info + std::unordered_map registered_instances; // void * -> PyObject* std::unordered_set, overload_hash> inactive_overload_cache; }; diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index e86a7fa2..b6de4311 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -204,7 +204,7 @@ protected: const std::type_info *t = types[type_index++]; if (!t) pybind11_fail("Internal error while parsing type signature (1)"); - auto it = registered_types.find(t); + auto it = registered_types.find(std::type_index(*t)); if (it != registered_types.end()) { signature += ((const detail::type_info *) it->second)->type->tp_name; } else { @@ -524,7 +524,7 @@ protected: tinfo->type = (PyTypeObject *) type; tinfo->type_size = rec->type_size; tinfo->init_holder = rec->init_holder; - internals.registered_types_cpp[rec->type] = tinfo; + internals.registered_types_cpp[std::type_index(*(rec->type))] = tinfo; internals.registered_types_py[type] = tinfo; auto scope_module = (object) rec->scope.attr("__module__"); @@ -844,7 +844,7 @@ public: template class_ alias() { auto &instances = pybind11::detail::get_internals().registered_types_cpp; - instances[&typeid(target)] = instances[&typeid(type)]; + instances[std::type_index(typeid(target))] = instances[std::type_index(typeid(type))]; return *this; } private: @@ -976,8 +976,8 @@ template void implicitly_convertible() PyErr_Clear(); return result; }; - auto & registered_types = detail::get_internals().registered_types_cpp; - auto it = registered_types.find(&typeid(OutputType)); + auto ®istered_types = detail::get_internals().registered_types_cpp; + auto it = registered_types.find(std::type_index(typeid(OutputType))); if (it == registered_types.end()) pybind11_fail("implicitly_convertible: Unable to find type " + type_id()); ((detail::type_info *) it->second)->implicit_conversions.push_back(implicit_caster);