Host Compiler & Generated Stubs
What It Is
The MetaFFI host compiler is an optional toolchain step that generates typed host-language wrappers for a foreign module. Instead of writing entity paths and type arrays by hand, you get a generated module you can import and call directly.
Benefits:
- Type safety — generated functions have typed signatures
- IDE autocomplete — your editor sees real functions, not opaque callables
- No stringly-typed code — entity paths and type arrays are handled for you
- Fewer runtime mistakes — type mismatches caught at generation time
The generated stubs call MetaFFI under the hood. Same runtime behavior, different ergonomics.
When to Use Each Mode
| Dynamic Loading | Generated Stubs | |
|---|---|---|
| Best for | Exploration, quick scripts, prototyping | Production codebases, large projects, CI |
| Setup | None — load and call at runtime | One-time metaffi -c command |
| Entity paths | Written by hand in app code | Generated for you |
| Type arrays | Written by hand in app code | Generated for you |
| IDE support | Limited (opaque callables) | Full (typed functions, autocomplete) |
| Performance | Same | Same (stubs are thin wrappers) |
Both modes use the same MetaFFI runtime. Stubs do not change runtime overhead — they change developer experience.
How It Works
- The host compiler reads a foreign module’s interface (via MetaFFI’s IDL layer)
- It emits host-language source code containing typed wrapper functions
- Each wrapper function calls
MetaFFIModule.load_entity()under the hood - You import the generated module and call functions normally
Source file (e.g., hello.go)
│
▼
metaffi -c --idl hello.go -h python3
│
▼
hello_MetaFFIHost.py (generated stubs)
│
▼
import hello_MetaFFIHost as hello
hello.SayHello("Python")
End-to-End Example: Call Go from Python
This example generates Python stubs for a Go module and calls it with typed functions.
Prerequisites
- MetaFFI installed (Getting Started)
- Go and Python3 language plugins installed
1. Write the Go module
Create hello.go:
package main
import "fmt"
func SayHello(name string) string {
return fmt.Sprintf("Hello, %s! Greetings from Go.", name)
}
2. Compile and generate stubs
# Compile Go module for MetaFFI (guest) AND generate Python host stubs
metaffi -c --idl hello.go -g go -h python3
This produces:
hello_MetaFFIGuest.dll(or.soon Linux) — the compiled Go guest modulehello_MetaFFIHost.py— typed Python stubs
3. Use the generated stubs
Create main.py:
import hello_MetaFFIHost as hello
hello.bind_module_to_code("hello_MetaFFIGuest", "go")
result = hello.SayHello("Python")
print(result) # "Hello, Python! Greetings from Go."
Compare this to the dynamic loading version — no entity paths, no type arrays, just a function call.
4. Regenerate when the Go API changes
If you modify hello.go (add functions, change signatures), re-run the same command:
metaffi -c --idl hello.go -g go -h python3
The stubs are regenerated to match the updated API.
What the Generated Code Looks Like
The host compiler generates a Python module with:
- A
bind_module_to_code(module_path, runtime_plugin)initialization function - Typed wrapper functions for each exported function
- Classes for types that have constructors and instance methods
- Property accessors for fields and global variables
Example generated code (simplified):
# Generated by MetaFFI host compiler — do not edit
import metaffi
_runtime = None
_module = None
_say_hello_caller = None
def bind_module_to_code(module_path: str, runtime_plugin: str) -> None:
global _runtime, _module, _say_hello_caller
_runtime = metaffi.MetaFFIRuntime(runtime_plugin)
_runtime.load_runtime_plugin()
_module = _runtime.load_module(module_path)
_say_hello_caller = _module.load_entity(
"callable=SayHello",
(metaffi_type_info(metaffi_string8_type, "string", 0),),
(metaffi_type_info(metaffi_string8_type, "string", 0),))
def SayHello(name: str) -> str:
return _say_hello_caller(name)
The generated stubs handle all the entity path and type plumbing. Your application code just calls SayHello(name).
Supported Host Languages
The host compiler generates stubs for all supported MetaFFI languages:
| Host Language | Output | Source |
|---|---|---|
| Python 3 | .py module |
lang-plugin-python3/compiler |
| Go | .go source file |
lang-plugin-go/compiler |
| JVM | .jar with compiled classes |
lang-plugin-openjdk/compiler |
CLI Reference
# Guest compilation only (compile foreign module)
metaffi -c --idl <source_file> -g <guest_language>
# Host compilation only (generate stubs)
metaffi -c --idl <source_file> -h <host_language>
# Both at once
metaffi -c --idl <source_file> -g <guest_language> -h <host_language>
# Generate stubs for multiple host languages
metaffi -c --idl <source_file> -g <guest_language> -h python3 go
| Flag | Description |
|---|---|
-c |
Compile mode |
--idl <file> |
Source file or IDL JSON to compile |
-g <language> |
Guest language (produces _MetaFFIGuest library) |
-h <language...> |
Host language(s) (produces _MetaFFIHost stubs) |
See Also
- Getting Started — installation and first cross-language call
- Examples — code examples showing both modes
- API Reference — the dynamic loading API used under the hood
- Entity Path — entity path format (used by dynamic mode; generated for you in stub mode)