# flapigen turns a Rust interface file into JNI or C wrappers

> flapigen is a code generator that connects Rust libraries to other languages: you describe the exported surface in a foreign_class! interface file, and it emits JNI wrappers plus Java calling code, or C compatible wrappers plus C++ code. It is BSD-3-Clause licensed, at version 0.11.0, and it was renamed from rust_swig to avoid confusion with SWIG.

**Dushistov/flapigen-rs** — Tool for connecting programs or libraries written in Rust with other languages

- Repository: https://github.com/Dushistov/flapigen-rs
- Stars: 808 · Forks: 61
- Language: Rust
- License: BSD-3-Clause
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/dushistov-flapigen-rs

## A generator, not a runtime bridge

flapigen is a tool for connecting programs or libraries written in Rust with other languages, described in the README as a foreign language API generator. The wording matters, because it places the project firmly in the code generation camp.

There is no runtime component here. Nothing is linked into your process to translate calls at runtime, and there is no C ABI shim library that both sides load. Instead, flapigen reads a description of the interface you want to expose and writes out the glue code, in both directions, so the calling language can use the Rust implementation as if it were native.

The supported targets are C++ and Java. The README notes that you can write support for any language of your choice, which is true of code generators in general, since the output is text, but the two implemented backends are the ones with test coverage in the repository.

The project was formerly called rust_swig, and the README gives the reason for the rename: to not confuse it with SWIG, the other well known binding generator. That is a small detail with a real effect, because searching for a Rust binding generator and landing on the wrong project is an easy mistake to make.

The licence is BSD-3-Clause, and the current version is 0.11.0, published on 2026-04-04, after 0.9.0 in April 2025 and 0.8.0 in November 2024. The last push to the repository was on 2026-10-12.

## The interface file is the contract everything is generated from

The way flapigen works is that you write one interface file in your Rust project, and the generator turns it into wrappers on both sides.

The README's example starts with a plain Rust struct and an impl, the kind of code you would have anyway.

```rust
struct Foo {
    data: i32
}

impl Foo {
    fn new(val: i32) -> Foo {
        Foo{data: val}
    }

    fn f(&self, a: i32, b: i32) -> i32 {
        self.data + a + b
    }

    fn set_field(&mut self, v: i32) {
        self.data = v;
    }
}
```

The interface file then describes, in a macro, which of those items are exposed and how.

```rust
foreign_class!(class Foo {
    self_type Foo;
    constructor Foo::new(_: i32) -> Foo;
    fn Foo::set_field(&mut self, _: i32);
    fn Foo::f(&self, _: i32, _: i32) -> i32;
    fn f2(_: i32) -> i32;
});
```

That single macro invocation is the entire surface definition. The self_type line names the Rust type, the constructor line describes how the foreign side creates it, and each function line names the Rust path, the self mutability and the argument and return types. The placeholder names are filled in by the foreign language's own parameter names.

The design is worth pausing on, because the interface file is the only thing a user has to maintain. Everything downstream, the JNI layer, the Java classes, the C shims and the C++ header, is produced from it, so the cost of exposing a function is one line in one file, and the cost of changing the wrapper side is zero.

## JNI for Java, a C ABI for C++

What comes out of the generator depends on the target, and the README describes both cases.

For Java, flapigen generates JNI wrappers for the Rust functions and Java code to call those JNI functions. The result is a Java class that looks like an ordinary Java API, with the JNI layer underneath it and the Rust implementation behind that. The Java code in the README's example is a constructor call and a method call, and nothing in it hints that the implementation is in Rust.

For C++, flapigen generates C compatible wrappers and C++ code to call those C functions. The difference is deliberate. C++ has no equivalent of JNI, so the portable surface is the C ABI, and the C++ side gets a header that wraps it in classes. Anything that can call C can therefore use the Rust code, and the C++ layer is a convenience rather than a requirement.

That split has a practical consequence for a team choosing a target. A Java codebase gets a native looking API and a JNI library to ship with it. A C++ codebase gets a stable C header, which is easier to vendor into a build system, easier to keep binary compatible across a recompile of the Rust side, and easier to consume from a language that is not C++ at all.

The interface file does not change between the two. The same foreign_class! description drives either output, so a project that supports both Java and C++ keeps one description of its Rust surface rather than two.

## rifgen for people who will not write the interface by hand

Writing the interface file is mechanical, and the README offers a way out of it.

If you want the interface file to be generated for you, the README points at rifgen, which is published on crates.io. The idea is that the tool reads your Rust source and produces the foreign_class! description, which you then review and check in.

That division of labour is the practical one. A hand written interface file is explicit and reviewable, and it is the thing that tells you exactly what is exposed to the other language, which is a security relevant fact. A generated one saves the typing but is only as good as the generator's idea of what should be public, so the file still has to be read before it is committed.

The repository itself is a good example of the interface-first approach, because the examples in it are the interface files.

The users guide is the third resource and it is where the integration details live, with the getting started page linked for how to integrate flapigen with a project, and the full guide hosted at dushistov.github.io/flapigen-rs/. The book/ directory in the tree is the source of that guide, which means the documentation is versioned alongside the code rather than living on a wiki that drifts.

## The test matrix tells you what is actually supported

The top level of the repository is mostly test directories, and their names describe the supported surface better than any feature list could.

There are cpp_tests/ and cpp_miri_tests/, where the second is the same C++ test suite run under Miri, an interpreter for Rust that checks undefined behaviour, which is a meaningful thing to run against generated C ABI code. There are jni_tests/ for the Java side, android-example/ and android-tests/ for the JNI path on a real mobile target, and python_tests/, which is a good sign for the project's direction even though Python is not one of the two supported output languages.

The glue code generator lives in macroslib/, which is the core of the tool. There is a debug-util/ directory for inspecting generated output, a book/ directory for the users guide, and a workspace.Cargo.toml at the root rather than a plain Cargo.toml, which is the sign of a workspace that is built as a set rather than as one crate.

The test tooling is Python. There is ci_build_and_test.py, which is presumably the continuous integration driver, and run-valgrind-buildscript-benchmark.py, which does three things at once: it runs the generated code under Valgrind to catch memory errors, it exercises the build script, and it measures something. The last of those is unusual. A binding generator that produces C code which is then linked into someone else's program is exactly the kind of tool where a memory bug in the generated code is a bug in the user's program, so running the generated output under a memory checker is a reasonable thing to insist on.

The .clang-format file and the .gitmodules file round out the picture, since the generated C and C++ code has to match a formatting style, and the repository pulls in some dependencies as submodules.

## Where flapigen is the wrong tool

Three situations rule it out.

The first is a target that is not C++ or Java. The README says support for other languages can be written, but that is a project in itself: a back end has to know how to marshal types, how to handle ownership and lifetimes across the boundary, and how to report errors. A team that needs Python, Go, Ruby or a scripting language binding today should look for a different approach, because writing a flapigen back end is more work than writing the bindings for a small surface by hand.

The second is a case where a runtime bridge is the right answer. If the Rust library is small, or the interface is still moving, then generating code for every change is overhead, and a crate such as PyO3 for Python or cxx for C++ does the same job with less machinery. The trade is between the stability of a compiled interface and the flexibility of one that adapts at run time.

The third is a project that needs a rich object model across the boundary. The interface file exposes classes, constructors, methods and functions, and it is good at that. It is not a mechanism for exposing Rust traits, iterators, closures, or lifetimes that borrow from the caller, and if your API depends on those, the language boundary is the real design problem and no generator solves it for you.

For the case it was built for, a Rust library with a stable, well typed surface that a Java or C++ application needs to call, flapigen removes the entire hand written FFI layer and the maintenance that comes with it.

## Conclusion

flapigen fits a team that already has a Rust core and needs to expose it to an existing Java or C++ codebase without hand writing the FFI layer, because the generated wrappers and the caller side are both produced from one interface file. It is the wrong choice if you need Python, Go or another target today, because the supported set is C++ and Java, and the wrong choice if you want a runtime bridge with no generated code at all. Before you start, read the getting started page for your build system, and plan to use rifgen if you do not want to write the interface file by hand, since the interface file is the artefact everything else is generated from.

## FAQ

### What is flapigen and what does it generate?

flapigen is a foreign language API generator for connecting Rust libraries to other languages. From one foreign_class! interface file it generates JNI wrappers and Java calling code for a Java target, or C compatible wrappers and C++ code for a C++ target.

### Which languages does flapigen support?

C++ and Java are the implemented ones, according to the README, which also says you can write support for any language of your choice. The repository carries cpp_tests/, cpp_miri_tests/, jni_tests/ and android-tests/ directories for the two supported paths.

### What is rifgen and how does it relate to flapigen?

rifgen is a separate crate published on crates.io that generates the interface file, the file containing the foreign_class! macro, for you from your Rust source, so you do not have to write that description by hand.

### Why was flapigen renamed from rust_swig?

The README states the former name rust_swig was changed to avoid confusion with SWIG, the other well known binding generator, and the project is now called flapigen.

### What licence is flapigen released under?

The repository is BSD-3-Clause licensed, with the LICENSE file at the root of the tree. The current version is 0.11.0, published on 2026-04-04, and the last push to the repository was on 2026-10-12.

## Sources

- [Dushistov/flapigen-rs on GitHub](https://github.com/Dushistov/flapigen-rs)
- [Issues](https://github.com/Dushistov/flapigen-rs/issues)
- [License: BSD-3-Clause](https://github.com/Dushistov/flapigen-rs/blob/master/LICENSE)
- [README](https://github.com/Dushistov/flapigen-rs/blob/master/README.md)
- [Releases](https://github.com/Dushistov/flapigen-rs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dushistov-flapigen-rs
