interoptopus_backend_csharp

Crates.iointeroptopus_backend_csharp
lib.rsinteroptopus_backend_csharp
version0.14.25
sourcesrc
created_at2021-06-13 22:34:23.999304
updated_at2024-06-20 08:56:24.915664
descriptionGenerates C# bindings.
homepage
repositoryhttps://github.com/ralfbiedert/interoptopus
max_upload_size
id409704
size854,186
Ralf Biedert (ralfbiedert)

documentation

https://docs.rs/interoptopus_backend_csharp/

README

Generates C# bindings for Interoptopus.

Usage

Assuming you have written a crate containing your FFI logic called example_library_ffi and want to generate C# bindings, follow the instructions below.

Inside Your Library

Add Interoptopus attributes to the library you have written, and define an inventory function listing all symbols you wish to export. An overview of all supported constructs can be found in the reference project.

use interoptopus::{ffi_function, ffi_type, Inventory, InventoryBuilder, function};

#[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) -> Vec2 {
    input
}

pub fn my_inventory() -> Inventory {
    InventoryBuilder::new()
        .register(function!(my_function))
        .inventory()
}

Add these to your Cargo.toml so the attributes and the binding generator can be found (replace ... with the latest version):

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
interoptopus = "..."
interoptopus_backend_csharp = "..."

Create a unit test in tests/bindings.rs which will generate your bindings when run with cargo test. In real projects you might want to add this code to another crate instead:

use interoptopus::util::NamespaceMappings;
use interoptopus::{Error, Interop};

#[test]
fn bindings_csharp() -> Result<(), Error> {
    use interoptopus_backend_csharp::{Config, Generator};
    use interoptopus_backend_csharp::overloads::{DotNet, Unity};

    let config = Config {
        dll_name: "example_library".to_string(),
        namespace_mappings: NamespaceMappings::new("My.Company"),
        ..Config::default()
    };

    Generator::new(config, example_library_ffi::my_inventory())
        .add_overload_writer(DotNet::new())
        //.add_overload_writer(Unity::new())
        .write_file("bindings/csharp/Interop.cs")?;

    Ok(())
}

Now run cargo test.

If anything is unclear you can find a working sample on Github.

Generated Output

The output below is what this backend might generate. Have a look at the [Config] struct if you want to customize something. If you really don't like how something is generated it is easy to create your own.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using My.Company;

namespace My.Company
{
    public static partial class InteropClass
    {
        public const string NativeLib = "example_library";

        /// Function using the type.
        [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "my_function")]
        public static extern Vec2 my_function(Vec2 input);
    }

    /// A simple type in our FFI layer.
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public partial struct Vec2
    {
        public float x;
        public float y;
    }
}
Commit count: 552

cargo fmt