Crate interoptopus[][src]

Expand description

Latest Version docs MIT Rust Rust

Interoptopus 🐙

The polyglot bindings generator for your library (C#, C, Python, …)


Huh?

  • Imagine you are writing this cool API and want the world to have it.
  • The world, however, is running Unity, C, Python, … all at the same time.
  • “Not a problem”, you say, “I’ll just use Interoptopus”.

And you’ll live happily* ever after.

*Actual results may depend on other life choices.

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# (incl. Unity)interoptopus_backend_csharpInterop.cs
Cinteroptopus_backend_cmy_header.h
Python CFFIinteroptopus_backend_cpython_cffireference.py
Your languageWrite your own backend1-

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

Getting Started 🍼

If you …

Features

  • explicit, type-safe, single source of truth API definition in Rust,
  • quality-of-life patterns on both sides (e.g., options, slices, services, …)
  • minimal on dependencies, build time, tooling impact,
  • if your project compiles your bindings should work*cough* (i.e., generated and callable),
  • extensible, multiple backends, easy to support new languages, fully customizable,
  • no scripts needed, cargo build + cargo test can produce and test (if lang installed) generated bindings

Supported Rust Constructs

See the reference project; it lists all supported constructs including:

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

As a rule of thumb we recommend to be slightly conservative with your signatures and always “think C”, since other languages don’t track lifetimes well and it’s is easy to accidentally pass an outlived pointer or doubly alias a &mut X on reentrant functions.

Performance 🏁

Generated low-level bindings should be “zero cost” w.r.t. hand-crafted bindings for that language. However, even hand-crafted bindings have an inherent, language-specific cost. For C# that cost can be almost 0, for Python CFFI it can be high. Patterns and convenience helpers might add additional overhead.

If you need API design guidance the following (wip) C# call-cost table🔥 can help.

Current Status

  • June 20, 2021 - Alpha. Has generated simple workingTM bindings for a few projects for a week now, many things missing.
  • June 13, 2021 - Pre-alpha. Has generated C#, C, Python-CFFI bindings at least once, many things missing, untested.

FAQ

Contributing

PRs are welcome.

  • Bug fixes can be submitted directly. Major changes should be filed as issues first.

  • Anything that would make previously working bindings change behavior or stop compiling is a major change; which doesn’t mean we’re opposed to breaking stuff before 1.0, 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.

testingtesting

Test generated bindings for various languages.

Helpers for backend authors.

Types used by backends to produce pretty output.

Macros

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

inventoryderive

The macro to define your library, ties everything together!

Defines a new API entry function and corresponding struct.

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

Defines a Service pattern and generate FFI wrapper code.

Defines a Service pattern, usually producing a class in OO languages.

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.

ffi_typederive

Enable a struct or enum to appear in generated bindings.