MCPcopy Index your code
hub / github.com/evanw/miniffi

github.com/evanw/miniffi @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
6,648 symbols 16,642 edges 584 files 19 documented · 0%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

miniffi

[!WARNING] This project is on its first release. I'm still trying out the idea. It has not been used in production.

This is a simple but opinionated FFI system for Rust. It allows you to call Rust code from other languages, and vice versa. Some design principles:

  • Intended for writing platform-agnostic Rust with platform-specific details in the host language
  • FFI support is split into data (structs passed by copy) and code (traits passed by reference)
  • Rather than have a separate schema language, the public API in your lib.rs is your schema
  • The generated binding code is compact, dependency-free, and straightforward to integrate with

Supported Features

  • Primitive types (bool, i32, f64, String, etc.)
  • Tuples
  • Structs
  • Enums
  • Top-level constants
  • Top-level functions
  • Traits (must be either Box<dyn T> or Rc<dyn T>)
  • Vec<T>
  • Option<T>
  • Box<T>

Available Targets

  • JavaScript/TypeScript (WASM)
  • Swift
  • C++

Example

After setting everything up, using miniffi looks something like this. The following example Rust code (in lib.rs) demonstrates passing code and data back and forth between Rust and the host language:

pub enum Level {
    Warning,
    Error,
}

pub trait Logger {
    fn log(&self, level: Level, text: &str);
}

pub trait Demo {
    fn run(&self, logger: Box<dyn Logger>);
}

pub fn get_demo() -> Box<dyn Demo> {
    struct DemoImpl;
    impl Demo for DemoImpl {
        fn run(&self, logger: Box<dyn Logger>) {
            logger.log(Level::Warning, "example");
        }
    }
    Box::new(DemoImpl)
}

// This includes the binding code generated by miniffi
include!(concat!(env!("OUT_DIR"), "/miniffi.rs"));

Unlike other FFI systems, there are no annotations required to expose something from lib.rs to the host language other than using pub to mark things public. The miniffi build script parses lib.rs, extracts the supported parts of the public API, and generates FFI binding code both for Rust (the miniffi.rs file referenced above) and for the host language. Calling that example Rust code might look like this:

In JavaScript/TypeScript:

import * as rust from "./miniffi.js"
import fs from "fs"

await rust.instantiate(fs.readFileSync(
    "./target/wasm32-unknown-unknown/debug/example.wasm"))

rust.get_demo().run({
    log(level, text) {
        if (level === rust.Level.Error)
            console.error("ERROR:", text)
        else if (level === rust.Level.Warning)
            console.warn("WARNING:", text)
    }
})

In Swift:

class LoggerImpl : Logger {
    func log(_ level: Level, _ text: String) {
        if level == .Error {
            print("ERROR:", text)
        } else if level == .Warning {
            print("WARNING:", text)
        }
    }
}

get_demo().run(LoggerImpl())

In C++:

#include <iostream>
#include "ffi.h"

struct LoggerImpl : rust::Logger {
    void log(rust::Level level, std::string text) {
        if (level == rust::Level::Error)
            std::cout << "ERROR: " << text << std::endl;
        else if (level == rust::Level::Warning)
            std::cout << "WARNING: " << text << std::endl;
    }
};

int main() {
    rust::get_demo()->run(std::make_unique<LoggerImpl>());
    return 0;
}

More information about how to use miniffi can be found in the documentation.

Similar Projects

These projects are much further along, and you may want to use them instead:

Extension points exported contracts — how you extend this code

Compile (Interface)
(no doc) [4 implementers]
src/lib.rs
Target (Interface)
The common trait for all language-specific targets. The following targets are available: - [`CppTarget`] for C++ - [`S [1 …
src/lib.rs

Core symbols most depended-on inside this repo

create
called by 203
src/util.rs
rust_mem_leaked
called by 153
src/tests/snapshots/wasm_demo_app_2021/ffi.mjs
find
called by 136
src/util.rs
line
called by 134
src/util.rs
decl
called by 101
src/util.rs
mark_used
called by 95
src/util.rs
push_ts
called by 81
src/wasm.rs
add_group
called by 81
src/util.rs

Shape

Function 4,711
Method 1,265
Class 644
Enum 26
Interface 2

Languages

Rust56%
C++24%
TypeScript20%

Modules by API surface

src/tests/snapshots/wasm_demo_keyword_2024/ffi.mjs146 symbols
src/tests/snapshots/wasm_demo_keyword_2021/ffi.mjs146 symbols
src/tests/snapshots/wasm_demo_keyword_2024/miniffi.rs144 symbols
src/tests/snapshots/wasm_demo_keyword_2021/miniffi.rs144 symbols
src/tests/snapshots/swift_demo_keyword_2024/miniffi.rs144 symbols
src/tests/snapshots/swift_demo_keyword_2021/miniffi.rs144 symbols
src/tests/snapshots/cpp_demo_keyword_2024/miniffi.rs144 symbols
src/tests/snapshots/cpp_demo_keyword_2024/ffi.cpp144 symbols
src/tests/snapshots/cpp_demo_keyword_2021/miniffi.rs144 symbols
src/tests/snapshots/cpp_demo_keyword_2021/ffi.cpp144 symbols
src/tests/snapshots/wasm_demo_derive_eq_2024/ffi.mjs73 symbols
src/tests/snapshots/wasm_demo_derive_eq_2021/ffi.mjs73 symbols

For agents

$ claude mcp add miniffi \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact