+/*
+ * TODO: Make this use the uobject_module stuff so packages are not loaded
+ * more than once.
+ */
+static GTypeModule *
+open_import_package(UObject *uo, const struct upkg_import *i)
+{
+ GTypeModule *pkg;
+
+ assert(i->parent == NULL);
+
+ if (strcmp(i->class_package, "Core") != 0
+ || strcmp(i->class_name, "Package") != 0) {
+ u_err(uo, "import root must be Core.Package");
+ return NULL;
+ }
+
+ pkg = u_pkg_open(i->name);
+ if (!pkg || !g_type_module_use(pkg)) {
+ u_err(uo, "failed to open package: %s", i->name);
+ return NULL;
+ }
+
+ if (!U_PKG(pkg)->pkg) {
+ g_type_module_unuse(pkg);
+ u_err(uo, "failed to open package: %s", pkg->name);
+ return NULL;
+ }
+
+ return pkg;
+}
+
+/* Find the export index of a package based on the import chain from another
+ * package. Returns the (non-negative) offset on success, or a negative value
+ * on failure. */
+static long resolve_import(struct upkg *pkg, const struct upkg_import *import)
+{
+ long current, index;
+
+ if (!import->parent)
+ return -1;
+
+ current = resolve_import(pkg, import->parent);
+ if (current != -1 && current >= 0)
+ return -42;
+
+ index = upkg_export_find(pkg, current, import->name);
+ if (index < 0)
+ return -42;
+
+ return index;
+}
+
+static GObject *get_import_object(UObject *uo, unsigned long index)
+{
+ const struct upkg_import *import;
+ GObject *obj = NULL;
+ GTypeModule *pkg;
+ long obj_index;
+
+ import = upkg_get_import(uo->pkg_file->pkg, index);
+ if (!import) {
+ u_err(uo, "invalid package import: %ld", index);
+ return NULL;
+ }
+
+ /* Get the package name at the top of the hierarchy. */
+ for (const struct upkg_import *i = import; i; i = i->parent) {
+ if (i->parent == NULL) {
+ pkg = open_import_package(uo, i);
+ if (!pkg)
+ return NULL;
+ }
+ }
+
+ obj_index = resolve_import(U_PKG(pkg)->pkg, import);
+ if (obj_index < 0) {
+ u_err(uo, "could not find import in package: %s", pkg->name);
+ goto out;
+ }
+
+ obj = u_object_new_from_package(pkg, obj_index);
+out:
+ g_type_module_unuse(pkg);
+ return obj;
+}
+