address issue with std::type_info across module boundaries (fixes #86)

This commit is contained in:
Wenzel Jakob 2016-01-29 11:39:32 +01:00
parent 2547ca468c
commit b6cf75d66a
3 changed files with 12 additions and 22 deletions

View File

@ -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);

View File

@ -71,6 +71,7 @@
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <typeindex>
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
@ -216,7 +217,7 @@ struct overload_hash {
/// Internal data struture used to track registered instances and types
struct internals {
std::unordered_map<const void *, void*> registered_types_cpp; // std::type_info* -> type_info
std::unordered_map<std::type_index, void*> registered_types_cpp; // std::type_index -> type_info
std::unordered_map<const void *, void*> registered_types_py; // PyTypeObject* -> type_info
std::unordered_map<const void *, void*> registered_instances; // void * -> PyObject*
std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;

View File

@ -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 <typename target> 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 <typename InputType, typename OutputType> void implicitly_convertible()
PyErr_Clear();
return result;
};
auto & registered_types = detail::get_internals().registered_types_cpp;
auto it = registered_types.find(&typeid(OutputType));
auto &registered_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<OutputType>());
((detail::type_info *) it->second)->implicit_conversions.push_back(implicit_caster);