Expand description
wrapped_mono
is a safe, lightweight wrapper around the mono library. It allows embedding of the mono runtime inside a rust project. Inside this embedded runtime code written in languages supporting the .NET framework, such as C# and F#, can be run. This allows usage of libraries written in those languages, and using them as a scripting language. The mono runtime is used by many game engines, and this wrapper allows using it with projects written in Rust too.
§Safety
Most functions are safe and when invalid data is passed will fail in a controlled way with an error message. There are still some pitfalls, because not all errors can be caught without substantial overhead. Those errors are hard to come by, and should be always clearly marked in the documentation(for example accessing an object after deleting it by deleting domain it is in), and easy to spot.
§Definitions of certain words used in documentation:
Managed Code - code which runs in the runtime(e.g. C# code)
Unmanaged code - code which runs outside runtime(in this case Rust code)
More precise explanation
§Feature flags
unsafe_boxing
— Disables boxing/unboxing safety checks. Normally, when an object is unboxed, it’s type is checked to prevent crashes and errors. Enabling unsafe_unboxing will make wrapped_mono assume that type given by the user is always correct.unsafe_arrays
— Disables array safety checks. Normally, when an array is created, it will make checks to ensure that its managed type matches its unmanaged type.unsafe_speedup
— Disables all safety checks to slightly speedwrapped_mono
up. Gains are usually negligible and potential errors will have more cryptic messages(Segfaluts instead of failed assertions). USE WITH CAUTION.build_test_dlls
— Build test dlls. Enable only for tests, if you want to change test .cs files.regen_binds
— Regenerates bindings for mono librarydump_macro_results
— Dumps code created as results of macros into “macro.dump” file. Use for debugging when macros do not behave as expected.referneced_objects
(enabled by default) — Prevents objects in use by rust from being removed by mono runtime, adds slight overhead but is essential for storing objects long term. Can be disabled, but disabling it forces manual management of object lifetimes using GC handles.old_gc_unsafe
— Uses some old variants of mono API. Try ifmono_threads_enter_gc_unsafe_region
symbol is missing during linking. Example
use wrapped_mono::*;
fn main(){
// Initialise the runtime with default version(`None`), and root domian named "main_domain"
let domain = jit::init("main_domain",None);
// Load assembly "SomeAssembly.dll"
let assembly = domain.assembly_open("SomeAssembly.dll").expect("Could not load assembly!");
// Get the image, the part of assembly containing executable code(classes,methods, etc.)
let image = assembly.get_image();
// Get class named SomeClass in SomeNamespace
let class = Class::from_name(&image,"SomeNamespace","SomeClass").expect("Could not find SomeClass!");
// Create an instance of this class
let instance = Object::new(&domain,&class);
// Creating an instance of a class DOES NOT CALL ITS CONSTRUCTOR. The constructor is a method named '.ctor', that has to be called separately
// Get a constructor method of SomeClass accepting an integer and a string (2 parameters)
let ctor:Method<(i32,String)> = Method::get_from_name(&class,".ctor(int,System.String)",2).expect("Could not find the constructor!");
// Call the constructor
ctor.invoke(Some(instance.clone()),(12,"SomeString".to_owned())).expect("Got an exception while calling the constructor!");
// Get a method "DoABackflip" form SomeClass with 1 parameter of type int returning a byte
let met:Method<(i32,String)> = Method::get_from_name(&class,"DoABackflip",1).expect("Could not find method \"DoABackFlip\"!");
// Call "DoABackflip" method on an instance
let res_obj = met.invoke(Some(instance),(32,"Message".to_owned())).expect("Got an exception while calling DoABackflip!").expect("Got null from DoABackFlip");
// Unbox the result to get a raw integer from a boxed integer
let res = res_obj.unbox::<u8>();
// Create a function with the special "invokable" attribute
#[invokable]
fn sqrt(input:f32)->f32{
if input < 0.0{
// can't get sqrt of a negative number, so create a managed exception and throw it.
unsafe{Exception::arithmetic().raise()};
}
input.sqrt()
}
// Replace a method with "[MethodImplAttribute(MethodImplOptions.InternalCall)]" atribute with a rust function
add_internal_call!("SomeClass::SqrtInternalCall",sqrt);
// This supports all types with `InteropRecive` trait
#[invokable]
fn avg(input:Array<Dim1D,f32>)->f32{
let mut avg = 0.0;
for i in 0..input.len(){
let curr = input.get([i]);// get the element at index i
avg += curr/(input.len() as f32);
}
avg
}
// Replace a method with "[MethodImplAttribute(MethodImplOptions.InternalCall)]" attribute with a rust function
add_internal_call!("SomeClass::AvgInternalCall",sqrt);
}
Re-exports§
pub use dimensions::*;
Modules§
- array
- Utilities related to managed arrays.
- assembly
- Functions and types related to
MonoAssembly
type. - bindgen
- class
- Representation of managed classes and utilities related to them.
- dimensions
- domain
- Safe representation of a delegate.
Functions and types related to
MonoDomain
type. - exception
- Utilities related to Exceptions.
- gc
- Functions related to garbage collection.
- image
- Part of assembly holding the executable code.
- interop
- Traits related to passing data between managed and unmanaged classes.
- jit
- Functions related to Mono JIT Runtime
- metadata
- Utilities related to metadata. Bare bones and experimental.
- method
- Safe representation of Methods(functions) form managed code an utilities related to managing and calling them.
- mstring
- Managed string utilities.
- object
- Utilities related to managed objects.
- reflection_
type - Safe representation of the
System.Type
type. - runtime
- Functions related to getting data about and configuring mono runtime.
- wrapped_
mono_ macros - Custom macros used by
wrapped_mono
Macros§
- add_
internal_ call - Macro equivalent of
mono_add_internal_call
with automatic support for type conversion. Allows you to expose a function as an internal call
Structs§
- Array
- Safe, rust representation of
MonoArray
(a reference to a managed array). - Assembly
- Safe representation of an executable file containing managed code and data about it.
- Class
- Safe representation of a managed class.(eg. System.Int64, System.Object, etc.);
- Class
Field - Representation of a class field. Accessors(getters,setters and indexers) are not fields, but properties! For them use
ClassProperity
- Class
Properity - Representation of class property(getters,setters) not a class field!
- Domain
- Safe representation of [
MonoDomain
] type. - Exception
- Safe representation of
MonoException
. - Image
- Safe representation of [
MonoImage
], the part of [MonoAssembly
] holding CLI code. - MString
- Representaiton of
Object
of type System.String. - Method
- Rust representation of a managed method(function of code loaded into mono runtime). Args - Tuple type of types of all arguments accepted by this particular method.
- Object
- Safe representation of a refernece to a manged Object. Is not nullable when passed between managed and unmanged code(e.g when added as an argument to function exposed as an interna call).
It means that while it may represent a nullable type, wrapped-mono will automaticly panic when recived null value.
For nullable support use
Option<Object>
. - Reflection
Type - Rust representation of managed object derived form class
System.Type
Traits§
- Interop
Box - Trait allowing for boxing and unboxing type from objects
- Interop
Class - Trait allowing managed class representing this type to be got.
Type of value
Self::InteropSend::TargetType
must match managed type represented byClass
returned byget_mono_class
. - Interop
Recive - Trait specifying how to convert a type when transferring it between managed and unmanaged code. It specifies how to convert
SourceType
used byMonoRuntime
to type implementing this trait. - Interop
Send - Trait specifying how to convert a type when transferring it between managed and unmanaged code. It specifies how to convert type implementing this trait
to
TargetType
used byMonoRuntime
. - Object
Trait - Trait contining functions common for all types of manged objects.
Attribute Macros§
- invokable
- Macro creating a wrapper around a function making it able to be exposed as internal call.
Derive Macros§
- Interop
Recive - Autoimplement
InteropRecive
trait for any type containing onlyIteropRecive
implementing memebers. Currently supports only structs, and trivial enums(C-like enums) of size less than u64(C# max enum size).