Crate magnus

source ·
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 ClassMagnus Type
StringRString
IntegerInteger
FloatFloat
ArrayRArray
HashRHash
SymbolSymbol
ClassRClass
ModuleRModule

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 required.

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_immediately, 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(())
}

C Function Index

Click to show

This lists all the Ruby C API functions currently implemented, and how they map to Rust functions and methods in Magnus.

A-N

RARRAY

RB

rb_a-rb_arx

rb_ary

rb_as-rb_az

rb_b

rb_c

rb_d

rb_e-rb_enb

rb_enc

rb_en-rb_ez

rb_f

rb_g

rb_h

rb_i-rb_in

rb_io

rb_is-rb_iz

rb_j-rb_k

  • rb_jump_tag: Return Error.

rb_l

rb_m

rb_n

rb_o

rb_p

rb_r

rb_s-rb_strl

rb_struct

rb_str

rb_st_

rb_sy-rb_sz

rb_t

rb_u

rb_v-rb_z

rc-rt

ruby_

S-Z

Re-exports

pub use crate::class::Class;
pub use crate::class::RClass;
pub use crate::error::Error;
pub use crate::exception::Exception;
pub use crate::exception::ExceptionClass;
pub use crate::module::Attr;
pub use crate::module::Module;
pub use crate::module::RModule;
pub use crate::r_hash::RHash;
pub use crate::r_string::RString;
pub use crate::r_struct::RStruct;
pub use crate::r_typed_data::DataType;
pub use crate::r_typed_data::DataTypeFunctions;
pub use crate::r_typed_data::RTypedData;
pub use crate::r_typed_data::TypedData;
pub use crate::value::Fixnum;
pub use crate::value::StaticSymbol;
pub use crate::value::Value;
pub use crate::value::QFALSE;
pub use crate::value::QNIL;
pub use crate::value::QTRUE;

Modules

Types and functions for working with Ruby blocks and Procs.
Types and functions for working with Ruby classes.
embedembed
Helpers for use when embedding Ruby in a Rust project.
Types and functions for working with encodings.
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.
rb_sysrb-sys-interop
Functions for interoperability with rb-sys.
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.
Create a RString from a Rust str literal.

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 type wrapping either a Flonum value or a Value known to be an instance of Float.
A Value known to be a flonum, Ruby’s internal representation of lower precision floating point numbers.
A type wrapping either a Fixnum or a RBignum.
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

Call the super method of the current method context.
Return the Ruby self of the current method context.
Define a class in the root scope.
Define an exception class in the root scope.
Define a global constant.
Define a method in the root scope.
Define a module in the root scope.
Define a global variable.
Evaluate a string of Ruby code, converting the result to a T.
Finds and loads the given feature if not already loaded.

Attribute Macros

Mark a function as the ‘init’ function to be run for a library when it is required 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.