Expand description
Magnus is a library for writing Ruby extentions in Rust, or running Ruby code from Rust.
Overview
All Ruby objects are represented by Value
. To make it easier to work
with values that are instances of specific classes a number of wrapper
types are available. These wrappers will Deref
to
Value
, so you can still use Value
’s methods on them.
Ruby Class | Magnus Type |
---|---|
String | RString |
Integer | Integer |
Float | Float |
Array | RArray |
Hash | RHash |
Symbol | Symbol |
Class | RClass |
Module | RModule |
When writing Rust code to be called from Ruby the init
attribute can
be used to mark your init function that Ruby will call when your library
is require
d.
When embedding Ruby in a Rust program, see [embed::init
] for initialising
the Ruby VM.
The method
macro can be used to wrap a Rust function
with automatic type conversion and error handing so it can be exposed to
Ruby. The TryConvert
trait handles conversions from Ruby to Rust, and
anything implementing Into<Value>
can be returned to Ruby. See the
Module
and Object
traits for defining methods.
Value::funcall
can be used to call Ruby methods from Rust.
See the wrap
attribute macro for wrapping Rust types as Ruby objects.
Safety
When using Magnus, in Rust code, Ruby objects must be kept on the stack. If objects are moved to the heap the Ruby GC can not reach them, and they may be garbage collected. This could lead to memory safety issues.
It is not possible to enforce this rule in Rust’s type system or via the borrow checker, users of Magnus must maintain this rule manually.
While it would be possible to mark any functions that could expose this
unsafty as unsafe
, that would mean that almost every interaction with
Ruby would be unsafe
. This would leave no way to differentiate the
really unsafe functions that need much more care to use.
Examples
use magnus::{define_module, function, method, prelude::*, Error};
#[magnus::wrap(class = "Euclid::Point", free_immediatly, size)]
struct Point {
x: isize,
y: isize,
}
impl Point {
fn new(x: isize, y: isize) -> Self {
Self { x, y }
}
fn x(&self) -> isize {
self.x
}
fn y(&self) -> isize {
self.y
}
}
fn distance(a: &Point, b: &Point) -> f64 {
(((b.x - a.x).pow(2) + (b.y - a.y).pow(2)) as f64).sqrt()
}
#[magnus::init]
fn init() -> Result<(), Error> {
let module = define_module("Euclid")?;
let class = module.define_class("Point", Default::default())?;
class.define_singleton_method("new", function!(Point::new, 2));
class.define_method("x", method!(Point::x, 0));
class.define_method("y", method!(Point::y, 0));
module.define_module_function("distance", function!(distance, 2));
Ok(())
}
Re-exports
pub use value::Fixnum;
pub use value::Flonum;
pub use value::StaticSymbol;
pub use value::Value;
pub use value::QFALSE;
pub use value::QNIL;
pub use value::QTRUE;
pub use class::RClass;
pub use error::Error;
pub use exception::Exception;
pub use exception::ExceptionClass;
pub use module::Module;
pub use module::RModule;
pub use r_hash::RHash;
pub use r_string::RString;
pub use r_struct::RStruct;
pub use r_typed_data::DataType;
pub use r_typed_data::DataTypeFunctions;
pub use r_typed_data::RTypedData;
pub use r_typed_data::TypedData;
Modules
Types and functions for working with Ruby blocks and Procs.
Types and functions for working with Ruby classes.
Rust types for working with Ruby Exceptions and other interrupts.
Types and functions for working with Ruby exceptions.
Functions for working with Ruby’s Garbage Collector.
Types and Traits for exposing Rust functions as Ruby methods.
Types and functions for working with Ruby modules.
Traits that commonly should be in scope.
Types and functions for working with Ruby’s Hash class.
Types for working with Ruby’s String class.
Types and functions for working with Ruby’s Struct class.
Types and Traits for wrapping Rust types as Ruby objects.
Types and functions for complex method arguments.
Types for working with Ruby’s VALUE type, representing all objects, and ‘immediate’ values such as Fixnum.
Macros
Evaluate a literal string of Ruby code with the given local variables.
Wrap a Rust function item with Ruby type conversion and error handling,
ignoring Ruby’s self
argument.
Utility to simplify initialising a static with std::sync::Once
.
Wrap a Rust function item with Ruby type conversion and error handling.
Structs
A Value known to be an instance of Binding.
Wrapper type for a Value known to be an instance of Ruby’s Enumerator class.
A Value pointer to a RArray struct, Ruby’s internal representation of an Array.
A Value pointer to a RBignum struct, Ruby’s internal representation of large integers.
A Value pointer to a RComplex struct, Ruby’s internal representation of complex numbers.
A Value pointer to a RFile struct, Ruby’s internal representation of files.
A Value pointer to a RFloat struct, Ruby’s internal representation of high precision floating point numbers.
A Value pointer to a RMatch struct, Ruby’s internal representation of the MatchData returned from a regex match.
A Value pointer to a RObject struct, Ruby’s internal representation of generic objects, not covered by the other R* types.
A Value pointer to a RRational struct, Ruby’s internal representation of rational numbers.
A Value pointer to a RRegexp struct, Ruby’s internal representation of regular expressions.
Wrapper type for a Value known to be an instance of Ruby’s Range class.
A type wrapping either a StaticSymbol
or a Value pointer to a RSymbol
struct.
Traits
Trait for types that can be used as an arguments list when calling Ruby methods.
Functions available all non-immediate values.
Conversions from Value
to Rust types.
Functions
Define a class in the root scope.
Define a method in the root scope.
Define a global variable.
Define a module in the root scope.
Evaluate a string of Ruby code, converting the result to a T
.
Attribute Macros
Mark a function as the ‘init’ function to be run for a library when it is
require
d by Ruby code.
Allow a Rust type to be passed to Ruby, automatically wrapped as a Ruby object.
Derive Macros
Derives DataTypeFunctions
with default implementations, for simple uses
of TypedData
.
Derives TypedData
, allowing the type to be passed to Ruby automatically
wrapped as a Ruby object.