Embedding › 03 Loading modules

Loading modules

Load compiled modules in the right order, and know where native libraries are found.

1. Dependencies come first

loth_engine_load links a module against the Engine's current contents. A module that references a class which is not loaded yet is rejected. The compiler emits the whole closure, so a host loads dependencies in order:

loth_engine_load(e, "build/Std.lothc");
loth_engine_load(e, "build/com/example/thread/Runnable.lothc");
loth_engine_load(e, "build/com/example/thread/Thread.lothc");
loth_engine_load(e, "build/com/example/App.lothc");

Common orders: Std first, then Runnable/Lock, then Cond (which needs Lock), then Thread/ThreadUtil (which need Runnable), then your application modules. Self-contained modules can be loaded in any order.

Failed loads are atomic: the function returns -1, prints the reason, and the Engine is unchanged. That makes it safe to skip optional plugins.

2. What loth compile writes

$ loth compile com/example/host/AppA.loth -o build
wrote build/com/example/host/AppA.lothc (703 bytes)
wrote build/Std.lothc (64 bytes)
wrote build/com/example/host/Shared.lothc (676 bytes)
...

Output mirrors the package path. A host loads these files by their relative path, as in the example above.

3. Where native .so files are found

When a module declares %native or %nativesimple classes, binding searches for the implementation in this order:

  1. <classpath>/<fqn as path>.so (set with native_set_cp_dir)
  2. <lib dir>/<fqn as path>.so (set with native_set_lib_dir)
  3. ./<fqn as path>.so

If no file matches the class name, the loader scans all .so files in the library directory and the working directory for one that registers the class. That is what lets a single library register several classes (for example lib/Thread.so provides Thread, ThreadUtil, Lock and Cond) without depending on import order.

Binding validates the library's metadata against the .loth declarations — class kind, fields, method signatures, slots — and refuses mismatches instead of half-binding.

4. Loading at run time (optional)

vm_load_module(vm, "plugins/Plugin.lothc");      // atomic; resolves dependencies; binds .so
vm_bind_native_file(vm, "plugins/Plugin.so");    // bind one library whose classes are already loaded

Dynamic loading is a startup activity in this version.

The module table is not protected against concurrent modification, so do not call vm_load_module while threads are running language code. Load everything you need before starting work.

5. Loading checklist