Interops

Using a custom DLL compiled from rust with a c# Interop in VB.NET

Below are the relevant code segments for each portion of the created interface (VB.net, Rust, C#).

Flow:

  • Create DLL from Rust code
  • Create Interop DLL from c# code generated from the Rust code.
  • Add reference to Interop DLL to VB.net solution
  • Execute code

Rust side:

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

#[ffi_function]
#[no_mangle]
pub extern "C" fn testfunc() {
println!("message: {}", hello_string(""));
}

fn hello_string(x: &str) -> &str {
    return "hello world";
}

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

Creation of the c# interop with Rust:

use interoptopus::util::NamespaceMappings;
use interoptopus::{Error, Interop};
use std::fs;
use std::path::Path;

#[test]
fn bindings_csharp() -> Result<(), Error> {
    use interoptopus_backend_csharp::{Config, Generator};
    use interoptopus_backend_csharp::overloads::{DotNet, Unity};
    let config = Config {
        dll_name: "testCustomDLL".to_string(),
        namespace_mappings: NamespaceMappings::new("testCustomDLL"),
        ..Config::default()
    };
    Generator::new(config, testCustomDLL::my_inventory())
        .add_overload_writer(DotNet::new())
        //.add_overload_writer(Unity::new())
        .write_file("bindings/testCustomDLL.cs")?;
    Ok(())
}

This is the generated Interop code which is compiled to DLL and referenced by the main solution:

// Automatically generated by Interoptopus.
#pragma warning disable 0105
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using testCustomDLL;
#pragma warning restore 0105
namespace testCustomDLL
{
    public static partial class Interop
    {
        public const string NativeLib = "testCustomDLL";

        static Interop()
        {
        }
        [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "testfunc")]
        public static extern void testfunc();
    }
    public class InteropException<T> : Exception
    {
        public T Error { get; private set; }
        public InteropException(T error): base($"Something went wrong: {error}")
        {
            Error = error;
        }
    }
}

VB.net Class that adds the Rust function:

Imports System.Runtime.InteropServices
Namespace classes
    Public Class NativeMethods
        <DllImport(".\dependencies\testCustomDLL.dll")>
        Public Shared Function testfunc()
        End Function
    End Class
End Namespace

VB.net code that calls the Rust function:

Private Func B_code_Click(sender As Object, e As RoutedEventArgs) Handles B_code.Click

    classes.NativeMethods.testfunc()

End Sub