Generates the code needed to call a function across processes on the same machine. If the function lives in another process, metropipe writes shared memory stubs. If it lives in the same process, metropipe can generate C function pointer stubs or linker-ready .so files — these are the same C ABI you'd use otherwise, just automated from your function signature.
| Situation | metropipe gives you | Notes |
|---|---|---|
| Same machine, different processes, different languages | Shared memory stubs with zero-copy layout. The generated code handles mmap, handshake, and byte layout. No server, no serialization, no configuration. | Faster than gRPC on localhost. No protos, no daemon. Without metropipe you'd write this from scratch for every language combination. |
| Same machine, same process, two languages | Generated C stubs. c-direct produces a function pointer registry. c-linker produces a .h + .c + Makefile you compile to a .so. |
These use the same C ABI you'd write by hand. metropipe generates them from your function signature so you don't type the boilerplate. |
| Different machines | Not the right tool. metropipe doesn't do networking. Use gRPC, Thrift, or HTTP. | |
| Async queuing or persistence | Not the right tool. metropipe doesn't store or queue messages. Use Kafka, NATS, or Redis. |
You have a Python function classify() in services.py. You want to call it from Rust or Go.
metropipe export classify services.py --target rust goThis reads the function signature from services.py and generates Rust and Go stubs with matching types. It also generates a provider script (metropipe/classify/provider.py) that imports your real classify() and runs it in a loop, waiting for requests over shared memory.
python3 metropipe/classify/provider.py &Now any process on the same machine that imports the generated Rust or Go stub can call classify() and get a result back. The stub writes arguments into a shared memory buffer at computed byte offsets, sets a status flag, and waits for the provider to respond. The provider reads the buffer, calls your real function, and writes the result back.
For cross-process stubs, metropipe calculates a binary layout where each parameter has a fixed byte offset: 4 bytes for int, 4 for float, 256 for string, 1 for bool. The generated stubs and the provider both know this layout — no serialization or encoding between them.
The shared memory file is created on first use. There is no server, daemon, or configuration.
metropipe export <function> <source> --target <lang> <lang> ...Supported targets: c-direct, c-linker, c (shared memory), go, python, java, rust, csharp, js, ruby, bash.
The three C targets:
c-direct— generates a function pointer registry. Openregistry.h, callmetropipe_get_registry()->classify(args). This is the same mechanism as a manual C plugin system, but metropipe writes the registration and lookup code.c-linker— generates.h+.c+Makefile. Runmaketo producelibclassify.so. This is the same process as writing a shared library by hand, but metropipe generates the interface files.c— shared memory stub for cross-process calls. No compilation, no linking, no server.
Output modes:
--namespace(default):metropipe/classify/stub.rs--flat:metropipe/classify.rs--unify:metropipe.rs(appends on subsequent exports)
Use --out <dir> to change output directory.
Without a source file, generates raw-bytes stubs you fill in yourself.
Source language detection from extension: .py, .rs, .go, .c, .h, .js, .mjs, .ts, .rb, .java, .cs. Unknown extensions produce raw-bytes stubs.
metropipe connect WeatherApiInteractive REPL over a shared memory channel. Lines are sent as request payloads, responses are printed. --send <data> for one-shot, --listen to act as provider, --gen-stubs to generate client library files.
Wraps the shared memory handshake as stdin/stdout. For languages that cannot call mmap (Bash, AWK, Perl, etc.):
echo "payload" | metropipe proxy WeatherApi > response.binReads a C header and generates stubs for all supported languages. Useful when you already have a library interface defined.
Since export knows the function signature at generation time, it calculates fixed byte offsets for each parameter. Both the stub and the provider use the same layout:
| Type | Buffer size |
|---|---|
| int32, float | 4 bytes |
| int64, double | 8 bytes |
| String | 256 bytes |
| bool | 1 byte |
| Data, bytes | 4096 bytes |
No encoding, no decoding, no allocation during the call.
Shared memory channels use a 32-byte header at the file start:
- bytes 0-3: status word (0=idle, 1=request, 3=response, 4=error)
- bytes 4-7: atomic lock
- bytes 8-11: payload size
- bytes 12-15: maximum capacity
- bytes 16-19: error code
- bytes 20-31: reserved
- bytes 32 onward: payload (zero-copy layout)
Path resolution: /dev/shm/metro_<name> (Linux), /tmp/metro_<name> (macOS), ./.metropipe/metro_<name> (fallback). Override with METROPIPE_DIR.
| Target | Generated file(s) | Mechanism |
|---|---|---|
| C (shm) | stub.h |
mmap + atomics |
| C (direct) | registry.h |
function pointer table |
| C (linker) | .h + .c + Makefile |
compiled .so |
| Go | stub.go |
syscall.Mmap |
| Python | stub.py |
mmap |
| Java | stub.java |
MappedByteBuffer |
| Rust | stub.rs |
mmap + libc |
| C# | stub.cs |
MemoryMappedFile |
| JavaScript | stub.js |
SharedArrayBuffer |
| Ruby | stub.rb |
IO.mmap |
| Bash | stub.sh |
calls metropipe proxy |
cargo install metropipePre-built binaries on the releases page.