Crate interoptopus[][src]

Expand description

Latest Version docs MIT Rust Rust

Interoptopus 🐙

The polyglot bindings generator for your library.

Code you write …

use interoptopus::{ffi_function, ffi_type, inventory};

#[ffi_type]
#[repr(C)]
pub struct Vec2 {
    pub x: f32,
    pub y: f32,
}

#[ffi_function]
#[no_mangle]
pub extern "C" fn my_function(input: Vec2) {
    println!("{}", input.x);
}

inventory!(ffi_inventory, [], [my_function], [], []);

… Interoptopus generates

LanguageCrateSample Output
C#interoptopus_backend_csharpInterop.cs
Cinteroptopus_backend_cmy_header.h
Python1interoptopus_backend_cpython_cffireference.py
OtherWrite your own backend2-

1 Using Python CFFI.
2 Create your own backend in just a few hours. No pull request needed. Pinkie promise.

Getting Started 🍼

If you want to …

Features

  • explicit, single source of truth API definition in Rust,
  • quality-of-life patterns (e.g., slices, services, …)
  • if your project compiles your bindings should work, *cough*
  • easy to support new languages, fully customizable,
  • no scripts needed, just cargo build + cargo test.

Gated behind feature flags, these enable:

  • derive - Proc macros such as ffi_type, …
  • serde - Serde attributes on internal types.
  • log - Invoke log on FFI errors.

Supported Rust Constructs

See the reference project for an overview:

  • functions (extern "C" functions and delegates)
  • types (composites, enums, opaques, references, …)
  • constants (primitive constants; results of const evaluation)
  • patterns (ASCII pointers, options, slices, classes, …)

Performance 🏁

Generated low-level bindings are “zero cost” w.r.t. hand-crafted bindings for that language.

That said, even hand-crafted bindings encounter some target-specific overhead at the FFI boundary (e.g., marshalling or pinning in managed languages) For C# that cost can be nanoseconds, for Python CFFI it can be microseconds.

See this C# call-cost table🔥 for ballpark figures.

Changelog

  • v0.10 - C# flavors DotNet and Unity (incl. Burst).
  • v0.9 - 150x faster C# slices, Python type hints.
  • v0.8 - Moved testing functions to respective backends.
  • v0.7 - Make patterns proc macros for better FFI docs.
  • v0.6 - Renamed and clarified many patterns.
  • v0.5 - More ergonomic slice usage in Rust and FFI.
  • v0.4 - Enable logging support in auto-generated FFI calls.
  • v0.3 - Better compatibility with generics.
  • v0.2 - Introduced “patterns”; working interop for C#.
  • v0.1 - First version.

Also see our upgrade instructions.

FAQ

Contributing

PRs are welcome.

  • Submit small bug fixes directly. Major changes should be issues first.
  • Anything that makes previously working bindings change behavior or stop compiling is a major change;
  • This doesn’t mean we’re opposed to breaking stuff just that we’d like to talk about it before it happens.
  • New features or patterns must be materialized in the reference project and accompanied by an interop test (i.e., a backend test running C# / Python against a DLL invoking that code) in at least one included backend.

Modules

Abstractions for authors of backends.

Optional types that translate to binding with better semantics in languages supporting them.

Test generated bindings for various languages.

Helpers for backend authors.

Types used by backends to produce pretty output.

Macros

Defines a callback type, akin to a fn f(T) -> R wrapped in an Option.

Debug macro resolving to the current file and line number.

Writes a line of code, possibly with multiple indentations. Used in backends.

The macro to define your library, ties everything together!

Structs

Represents all FFI-relevant items, produced via inventory, ingested by backends.

Enums

Can be observed if something goes wrong.

Traits

Main entry point for backends to generate language bindings.

Functions

Create a single Library from a number of individual libraries.

Attribute Macros

Enables a const to appear in generated bindings.

Enable an extern "C" function to appear in generated bindings.

Creates a FFI service from an impl Service {} block.

Inside a #[ffi_service] block, mark the FFI constructor.

Inside a #[ffi_service] block, provide special directives to functions.

On methods and structs, provide a type helper for foreign types.⚠️

ffi_typederive

Enable a struct or enum to appear in generated bindings.