Browse Source

Remove Python type tables from interrogatedb

rdb 7 years ago
parent
commit
e6f870ece6

+ 13 - 0
dtool/src/dtoolbase/typeHandle.cxx

@@ -153,6 +153,19 @@ deallocate_array(void *ptr) {
   PANDA_FREE_ARRAY(ptr);
 }
 
+/**
+ * Returns the internal void pointer that is stored for interrogate's benefit.
+ */
+PyObject *TypeHandle::
+get_python_type() const {
+  TypeRegistryNode *rnode = TypeRegistry::ptr()->look_up(*this, nullptr);
+  if (rnode != nullptr) {
+    return rnode->get_python_type();
+  } else {
+    return nullptr;
+  }
+}
+
 /**
  * Return the Index of the BEst fit Classs from a set
  */

+ 2 - 0
dtool/src/dtoolbase/typeHandle.h

@@ -138,6 +138,8 @@ PUBLISHED:
   MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
 
 public:
+  PyObject *get_python_type() const;
+
   void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
   void deallocate_array(void *ptr);

+ 16 - 0
dtool/src/dtoolbase/typeRegistry.cxx

@@ -207,6 +207,22 @@ record_alternate_name(TypeHandle type, const string &name) {
   _lock->unlock();
 }
 
+/**
+ * Records the given Python type pointer in the type registry for the benefit
+ * of interrogate.
+ */
+void TypeRegistry::
+record_python_type(TypeHandle type, PyObject *python_type) {
+  _lock->lock();
+
+  TypeRegistryNode *rnode = look_up(type, nullptr);
+  if (rnode != nullptr) {
+    rnode->_python_type = python_type;
+  }
+
+  _lock->unlock();
+}
+
 /**
  * Looks for a previously-registered type of the given name.  Returns its
  * TypeHandle if it exists, or TypeHandle::none() if there is no such type.

+ 1 - 0
dtool/src/dtoolbase/typeRegistry.h

@@ -45,6 +45,7 @@ PUBLISHED:
 
   void record_derivation(TypeHandle child, TypeHandle parent);
   void record_alternate_name(TypeHandle type, const std::string &name);
+  void record_python_type(TypeHandle type, PyObject *python_type);
 
   TypeHandle find_type(const std::string &name) const;
   TypeHandle find_type_by_id(int id) const;

+ 13 - 0
dtool/src/dtoolbase/typeRegistryNode.I

@@ -11,6 +11,19 @@
  * @date 2001-08-06
  */
 
+/**
+ * Returns the Python type object associated with this node.
+ */
+INLINE PyObject *TypeRegistryNode::
+get_python_type() const {
+  if (_python_type != nullptr || _parent_classes.empty()) {
+    return _python_type;
+  } else {
+    // Recurse through parent classes.
+    return r_get_python_type();
+  }
+}
+
 /**
  *
  */

+ 23 - 0
dtool/src/dtoolbase/typeRegistryNode.cxx

@@ -308,6 +308,29 @@ r_build_subtrees(TypeRegistryNode *top, int bit_count,
   }
 }
 
+/**
+ * Recurses through the parent nodes to find the best Python type object to
+ * represent objects of this type.
+ */
+PyObject *TypeRegistryNode::
+r_get_python_type() const {
+  Classes::const_iterator ni;
+  for (ni = _parent_classes.begin(); ni != _parent_classes.end(); ++ni) {
+    const TypeRegistryNode *parent = *ni;
+    if (parent->_python_type != nullptr) {
+      return parent->_python_type;
+
+    } else if (!parent->_parent_classes.empty()) {
+      PyObject *py_type = parent->r_get_python_type();
+      if (py_type != nullptr) {
+        return py_type;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
 /**
  * A recursive function to double-check the result of is_derived_from().  This
  * is the slow, examine-the-whole-graph approach, as opposed to the clever and

+ 5 - 0
dtool/src/dtoolbase/typeRegistryNode.h

@@ -37,6 +37,8 @@ public:
   static TypeHandle get_parent_towards(const TypeRegistryNode *child,
                                        const TypeRegistryNode *base);
 
+  INLINE PyObject *get_python_type() const;
+
   void clear_subtree();
   void define_subtree();
 
@@ -46,6 +48,7 @@ public:
   typedef std::vector<TypeRegistryNode *> Classes;
   Classes _parent_classes;
   Classes _child_classes;
+  PyObject *_python_type = nullptr;
 
   AtomicAdjust::Integer _memory_usage[TypeHandle::MC_limit];
 
@@ -77,6 +80,8 @@ private:
   void r_build_subtrees(TypeRegistryNode *top,
                         int bit_count, SubtreeMaskType bits);
 
+  PyObject *r_get_python_type() const;
+
   static bool check_derived_from(const TypeRegistryNode *child,
                                  const TypeRegistryNode *base);
 

+ 74 - 40
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -821,10 +821,54 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     }
   }
 
+  out_code << "/**\n";
+  out_code << " * Declarations for exported classes\n";
+  out_code << " */\n";
+
+  out_code << "static const Dtool_TypeDef exports[] = {\n";
+
+  for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
+    Object *object = (*oi).second;
+
+    if (object->_itype.is_class() || object->_itype.is_struct()) {
+      CPPType *type = object->_itype._cpptype;
+
+      if (isExportThisRun(type) && is_cpp_type_legal(type)) {
+        string class_name = type->get_local_name(&parser);
+        string safe_name = make_safe_name(class_name);
+
+        out_code << "  {\"" << class_name << "\", &Dtool_" << safe_name << "},\n";
+      }
+    }
+  }
+
+  out_code << "  {nullptr, nullptr},\n";
+  out_code << "};\n\n";
+
   out_code << "/**\n";
   out_code << " * Extern declarations for imported classes\n";
   out_code << " */\n";
 
+  // Write out a table of the externally imported types that will be filled in
+  // upon module initialization.
+  if (!_external_imports.empty()) {
+    out_code << "#ifndef LINK_ALL_STATIC\n";
+    out_code << "static Dtool_TypeDef imports[] = {\n";
+
+    int idx = 0;
+    for (CPPType *type : _external_imports) {
+      string class_name = type->get_local_name(&parser);
+      string safe_name = make_safe_name(class_name);
+
+      out_code << "  {\"" << class_name << "\", nullptr},\n";
+      out_code << "#define Dtool_Ptr_" << safe_name << " (imports[" << idx << "].type)\n";
+      ++idx;
+    }
+    out_code << "  {nullptr, nullptr},\n";
+    out_code << "};\n";
+    out_code << "#endif\n\n";
+  }
+
   for (CPPType *type : _external_imports) {
     string class_name = type->get_local_name(&parser);
     string safe_name = make_safe_name(class_name);
@@ -834,7 +878,9 @@ write_prototypes(ostream &out_code, ostream *out_h) {
     out_code << "#ifndef LINK_ALL_STATIC\n";
     // out_code << "IMPORT_THIS struct Dtool_PyTypedObject Dtool_" <<
     // safe_name << ";\n";
-    out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n";
+    //if (has_get_class_type_function(type)) {
+    //  out_code << "static struct Dtool_PyTypedObject *Dtool_Ptr_" << safe_name << ";\n";
+    //}
     // out_code << "#define Dtool_Ptr_" << safe_name << " &Dtool_" <<
     // safe_name << "\n"; out_code << "IMPORT_THIS void
     // Dtool_PyModuleClassInit_" << safe_name << "(PyObject *module);\n";
@@ -1258,36 +1304,36 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
 
   Objects::iterator oi;
 
-  out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n";
+  out << "void Dtool_" << def->library_name << "_RegisterTypes() {\n"
+         "  TypeRegistry *registry = TypeRegistry::ptr();\n"
+         "  nassertv(registry != nullptr);\n";
+
   for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
     Object *object = (*oi).second;
-    if (object->_itype.is_class() ||
-        object->_itype.is_struct()) {
-      if (is_cpp_type_legal(object->_itype._cpptype) &&
-          isExportThisRun(object->_itype._cpptype)) {
-        string class_name = make_safe_name(object->_itype.get_scoped_name());
-        bool is_typed = has_get_class_type_function(object->_itype._cpptype);
+    if (object->_itype.is_class() || object->_itype.is_struct()) {
+      CPPType *type = object->_itype._cpptype;
+      if (is_cpp_type_legal(type) && isExportThisRun(type)) {
+        string class_name = object->_itype.get_scoped_name();
+        string safe_name = make_safe_name(class_name);
+        bool is_typed = has_get_class_type_function(type);
 
         if (is_typed) {
-          if (has_init_type_function(object->_itype._cpptype)) {
+          out << "  {\n";
+          if (has_init_type_function(type)) {
             // Call the init_type function.  This isn't necessary for all
             // types as many of them are automatically initialized at static
             // init type, but for some extension classes it's useful.
-            out << "  " << object->_itype._cpptype->get_local_name(&parser)
+            out << "    " << type->get_local_name(&parser)
                 << "::init_type();\n";
           }
-          out << "  Dtool_" << class_name << "._type = "
-              << object->_itype._cpptype->get_local_name(&parser)
-              << "::get_class_type();\n"
-              << "  RegisterRuntimeTypedClass(Dtool_" << class_name << ");\n";
-
+          out << "    TypeHandle handle = " << type->get_local_name(&parser)
+              << "::get_class_type();\n";
+          out << "    Dtool_" << safe_name << "._type = handle;\n";
+          out << "    registry->record_python_type(handle, "
+                 "(PyObject *)&Dtool_" << safe_name << ");\n";
+          out << "  }\n";
         } else {
-          out << "#ifndef LINK_ALL_STATIC\n"
-              << "  RegisterNamedClass(\"" << object->_itype.get_scoped_name()
-              << "\", Dtool_" << class_name << ");\n"
-              << "#endif\n";
-
-          if (IsPandaTypedObject(object->_itype._cpptype->as_struct_type())) {
+          if (IsPandaTypedObject(type->as_struct_type())) {
             nout << object->_itype.get_scoped_name() << " derives from TypedObject, "
                  << "but does not define a get_class_type() function.\n";
           }
@@ -1297,23 +1343,6 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
   }
   out << "}\n\n";
 
-  out << "void Dtool_" << def->library_name << "_ResolveExternals() {\n";
-  out << "#ifndef LINK_ALL_STATIC\n";
-  out << "  // Resolve externally imported types.\n";
-
-  for (CPPType *type : _external_imports) {
-    string class_name = type->get_local_name(&parser);
-    string safe_name = make_safe_name(class_name);
-
-    if (has_get_class_type_function(type)) {
-      out << "  Dtool_Ptr_" << safe_name << " = LookupRuntimeTypedClass(" << class_name << "::get_class_type());\n";
-    } else {
-      out << "  Dtool_Ptr_" << safe_name << " = LookupNamedClass(\"" << class_name << "\");\n";
-    }
-  }
-  out << "#endif\n";
-  out << "}\n\n";
-
   out << "void Dtool_" << def->library_name << "_BuildInstants(PyObject *module) {\n";
   out << "  (void) module;\n";
 
@@ -1466,9 +1495,14 @@ write_module_support(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
 
   out << "  {nullptr, nullptr, 0, nullptr}\n" << "};\n\n";
 
-  out << "struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs};\n";
+  out << "extern const struct LibraryDef " << def->library_name << "_moddef = {python_simple_funcs, exports, ";
+  if (_external_imports.empty()) {
+    out << "nullptr};\n";
+  } else {
+    out << "imports};\n";
+  }
   if (out_h != nullptr) {
-    *out_h << "extern struct LibraryDef " << def->library_name << "_moddef;\n";
+    *out_h << "extern const struct LibraryDef " << def->library_name << "_moddef;\n";
   }
 }
 

+ 3 - 10
dtool/src/interrogate/interrogate_module.cxx

@@ -286,9 +286,8 @@ int write_python_table_native(std::ostream &out) {
   vector_string::const_iterator ii;
   for (ii = libraries.begin(); ii != libraries.end(); ++ii) {
     printf("Referencing Library %s\n", (*ii).c_str());
-    out << "extern LibraryDef " << *ii << "_moddef;\n";
+    out << "extern const struct LibraryDef " << *ii << "_moddef;\n";
     out << "extern void Dtool_" << *ii << "_RegisterTypes();\n";
-    out << "extern void Dtool_" << *ii << "_ResolveExternals();\n";
     out << "extern void Dtool_" << *ii << "_BuildInstants(PyObject *module);\n";
   }
 
@@ -339,12 +338,9 @@ int write_python_table_native(std::ostream &out) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
   }
-  for (ii = libraries.begin(); ii != libraries.end(); ii++) {
-    out << "  Dtool_" << *ii << "_ResolveExternals();\n";
-  }
   out << "\n";
 
-  out << "  LibraryDef *defs[] = {";
+  out << "  const LibraryDef *defs[] = {";
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "&" << *ii << "_moddef, ";
   }
@@ -386,12 +382,9 @@ int write_python_table_native(std::ostream &out) {
   for (ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "  Dtool_" << *ii << "_RegisterTypes();\n";
   }
-  for (ii = libraries.begin(); ii != libraries.end(); ii++) {
-    out << "  Dtool_" << *ii << "_ResolveExternals();\n";
-  }
   out << "\n";
 
-  out << "  LibraryDef *defs[] = {";
+  out << "  const LibraryDef *defs[] = {";
   for(ii = libraries.begin(); ii != libraries.end(); ii++) {
     out << "&" << *ii << "_moddef, ";
   }

+ 5 - 5
dtool/src/interrogatedb/py_panda.I

@@ -26,7 +26,7 @@
 template<class T> INLINE bool
 DtoolInstance_GetPointer(PyObject *self, T *&into) {
   if (DtoolInstance_Check(self)) {
-    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+    Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
     if (target_class != nullptr) {
       if (_IS_FINAL(T)) {
         if (DtoolInstance_TYPE(self) == target_class) {
@@ -116,28 +116,28 @@ INLINE long Dtool_EnumValue_AsLong(PyObject *value) {
  */
 template<class T> INLINE PyObject *
 DTool_CreatePyInstance(const T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, true);
 }
 
 template<class T> INLINE PyObject *
 DTool_CreatePyInstance(T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstance((void*) obj, *known_class, memory_rules, false);
 }
 
 template<class T> INLINE PyObject *
 DTool_CreatePyInstanceTyped(const T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, true, obj->get_type().get_index());
 }
 
 template<class T> INLINE PyObject *
 DTool_CreatePyInstanceTyped(T *obj, bool memory_rules) {
-  Dtool_PyTypedObject *known_class = Dtool_RuntimeTypeDtoolType(get_type_handle(T).get_index());
+  Dtool_PyTypedObject *known_class = (Dtool_PyTypedObject *)get_type_handle(T).get_python_type();
   nassertr(known_class != nullptr, nullptr);
   return DTool_CreatePyInstanceTyped((void*) obj, *known_class, memory_rules, false, obj->get_type().get_index());
 }

+ 48 - 101
dtool/src/interrogatedb/py_panda.cxx

@@ -29,10 +29,6 @@ PyMemberDef standard_type_members[] = {
   {nullptr}  /* Sentinel */
 };
 
-static RuntimeTypeMap runtime_type_map;
-static RuntimeTypeSet runtime_type_set;
-static NamedTypeMap named_type_map;
-
 /**
 
  */
@@ -431,7 +427,7 @@ PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &
   // IF the class is possibly a run time typed object
   if (type_index > 0) {
     // get best fit class...
-    Dtool_PyTypedObject *target_class = Dtool_RuntimeTypeDtoolType(type_index);
+    Dtool_PyTypedObject *target_class = (Dtool_PyTypedObject *)TypeHandle::from_index(type_index).get_python_type();
     if (target_class != nullptr) {
       // cast to the type...
       void *new_local_this = target_class->_Dtool_DowncastInterface(local_this_in, &known_class_type);
@@ -507,109 +503,30 @@ void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &themap) {
   }
 }
 
-// ** HACK ** alert.. Need to keep a runtime type dictionary ... that is
-// forward declared of typed object.  We rely on the fact that typed objects
-// are uniquly defined by an integer.
-void
-RegisterNamedClass(const string &name, Dtool_PyTypedObject &otype) {
-  std::pair<NamedTypeMap::iterator, bool> result =
-    named_type_map.insert(NamedTypeMap::value_type(name, &otype));
-
-  if (!result.second) {
-    // There was already a class with this name in the dictionary.
-    interrogatedb_cat.warning()
-      << "Double definition for class " << name << "\n";
-  }
-}
-
-void
-RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype) {
-  int type_index = otype._type.get_index();
-
-  if (type_index == 0) {
-    interrogatedb_cat.warning()
-      << "Class " << otype._PyType.tp_name
-      << " has a zero TypeHandle value; check that init_type() is called.\n";
-
-  } else if (type_index < 0 || type_index >= TypeRegistry::ptr()->get_num_typehandles()) {
-    interrogatedb_cat.warning()
-      << "Class " << otype._PyType.tp_name
-      << " has an illegal TypeHandle value; check that init_type() is called.\n";
-
-  } else {
-    std::pair<RuntimeTypeMap::iterator, bool> result =
-      runtime_type_map.insert(RuntimeTypeMap::value_type(type_index, &otype));
-    if (!result.second) {
-      // There was already an entry in the dictionary for type_index.
-      Dtool_PyTypedObject *other_type = (*result.first).second;
-      interrogatedb_cat.warning()
-        << "Classes " << otype._PyType.tp_name
-        << " and " << other_type->_PyType.tp_name
-        << " share the same TypeHandle value (" << type_index
-        << "); check class definitions.\n";
-
-    } else {
-      runtime_type_set.insert(type_index);
-    }
-  }
-}
-
-Dtool_PyTypedObject *
-LookupNamedClass(const string &name) {
-  NamedTypeMap::const_iterator it;
-  it = named_type_map.find(name);
-
-  if (it == named_type_map.end()) {
-    // Find a type named like this in the type registry.
-    TypeHandle handle = TypeRegistry::ptr()->find_type(name);
-    if (handle.get_index() > 0) {
-      RuntimeTypeMap::const_iterator it2;
-      it2 = runtime_type_map.find(handle.get_index());
-      if (it2 != runtime_type_map.end()) {
-        return it2->second;
-      }
-    }
-
-    interrogatedb_cat.error()
-      << "Attempt to use type " << name << " which has not yet been defined!\n";
-    return nullptr;
-  } else {
-    return it->second;
-  }
-}
-
-Dtool_PyTypedObject *
-LookupRuntimeTypedClass(TypeHandle handle) {
-  RuntimeTypeMap::const_iterator it;
-  it = runtime_type_map.find(handle.get_index());
-
-  if (it == runtime_type_map.end()) {
-    interrogatedb_cat.error()
-      << "Attempt to use type " << handle << " which has not yet been defined!\n";
-    return nullptr;
+/**
+ * Returns a borrowed reference to the global type dictionary.
+ */
+Dtool_TypeMap *Dtool_GetGlobalTypeMap() {
+  PyObject *capsule = PySys_GetObject("_interrogate_types");
+  if (capsule != nullptr) {
+    return (Dtool_TypeMap *)PyCapsule_GetPointer(capsule, nullptr);
   } else {
-    return it->second;
+    Dtool_TypeMap *type_map = new Dtool_TypeMap;
+    capsule = PyCapsule_New((void *)type_map, nullptr, nullptr);
+    PySys_SetObject("_interrogate_types", capsule);
+    Py_DECREF(capsule);
+    return type_map;
   }
 }
 
 Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type) {
-  RuntimeTypeMap::iterator di = runtime_type_map.find(type);
-  if (di != runtime_type_map.end()) {
-    return di->second;
-  } else {
-    int type2 = get_best_parent_from_Set(type, runtime_type_set);
-    di = runtime_type_map.find(type2);
-    if (di != runtime_type_map.end()) {
-      return di->second;
-    }
-  }
-  return nullptr;
+  return (Dtool_PyTypedObject *)TypeHandle::from_index(type).get_python_type();
 }
 
 #if PY_MAJOR_VERSION >= 3
-PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], PyModuleDef *module_def) {
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def) {
 #else
-PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
+PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename) {
 #endif
   // Check the version so we can print a helpful error if it doesn't match.
   string version = Py_GetVersion();
@@ -672,10 +589,40 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
     Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(nullptr);
   }
 
+  Dtool_TypeMap *type_map = Dtool_GetGlobalTypeMap();
+
   // the module level function inits....
   MethodDefmap functions;
-  for (int xx = 0; defs[xx] != nullptr; xx++) {
-    Dtool_Accum_MethDefs(defs[xx]->_methods, functions);
+  for (size_t i = 0; defs[i] != nullptr; i++) {
+    const LibraryDef &def = *defs[i];
+    Dtool_Accum_MethDefs(def._methods, functions);
+
+    // Define exported types.
+    const Dtool_TypeDef *types = def._types;
+    if (types != nullptr) {
+      while (types->name != nullptr) {
+        (*type_map)[std::string(types->name)] = types->type;
+        ++types;
+      }
+    }
+  }
+
+  // Resolve external types, in a second pass.
+  for (size_t i = 0; defs[i] != nullptr; i++) {
+    const LibraryDef &def = *defs[i];
+
+    Dtool_TypeDef *types = def._external_types;
+    if (types != nullptr) {
+      while (types->name != nullptr) {
+        auto it = type_map->find(std::string(types->name));
+        if (it != type_map->end()) {
+          types->type = it->second;
+        } else {
+          return PyErr_Format(PyExc_NameError, "name '%s' is not defined", types->name);
+        }
+        ++types;
+      }
+    }
   }
 
   PyMethodDef *newdef = new PyMethodDef[functions.size() + 1];

+ 13 - 7
dtool/src/interrogatedb/py_panda.h

@@ -190,11 +190,9 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
 // forward declared of typed object.  We rely on the fact that typed objects
 // are uniquly defined by an integer.
 
-EXPCL_INTERROGATEDB void RegisterNamedClass(const std::string &name, Dtool_PyTypedObject &otype);
-EXPCL_INTERROGATEDB void RegisterRuntimeTypedClass(Dtool_PyTypedObject &otype);
+typedef std::map<std::string, Dtool_PyTypedObject *> Dtool_TypeMap;
 
-EXPCL_INTERROGATEDB Dtool_PyTypedObject *LookupNamedClass(const std::string &name);
-EXPCL_INTERROGATEDB Dtool_PyTypedObject *LookupRuntimeTypedClass(TypeHandle handle);
+EXPCL_INTERROGATEDB Dtool_TypeMap *Dtool_GetGlobalTypeMap();
 
 EXPCL_INTERROGATEDB Dtool_PyTypedObject *Dtool_RuntimeTypeDtoolType(int type);
 
@@ -326,14 +324,22 @@ EXPCL_INTERROGATEDB void Dtool_Accum_MethDefs(PyMethodDef in[], MethodDefmap &th
 // We need a way to runtime merge compile units into a python "Module" .. this
 // is done with the fallowing structors and code.. along with the support of
 // interigate_module
+
+struct Dtool_TypeDef {
+  const char *const name;
+  Dtool_PyTypedObject *type;
+};
+
 struct LibraryDef {
-  PyMethodDef *_methods;
+  PyMethodDef *const _methods;
+  const Dtool_TypeDef *const _types;
+  Dtool_TypeDef *const _external_types;
 };
 
 #if PY_MAJOR_VERSION >= 3
-EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], PyModuleDef *module_def);
+EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def);
 #else
-EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename);
+EXPCL_INTERROGATEDB PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename);
 #endif
 
 // HACK.... Be carefull Dtool_BorrowThisReference This function can be used to