pub struct VM;
Expand description
Virtual Machine and helpers
Implementations§
Source§impl VM
impl VM
Sourcepub fn init()
pub fn init()
Initializes Ruby virtual machine.
This function should ONLY be used if you write a standalone application which calls Ruby itself, for example:
-
Sidekiq-like background processing
-
Unicorn-like web server
In these cases it should be called before any interaction with Ruby.
If you write a library which is being connected to Ruby in runtime (e.g. some gem), this function should not be used.
§Examples
use ruru::{Class, VM};
VM::init();
// VM started, able to use Ruby now
// ...
Class::new("SomeClass", None); // etc
Sourcepub fn require(name: &str)
pub fn require(name: &str)
Requires Ruby source file.
§Examples
use ruru::VM;
VM::require("some_ruby_file");
Ruby:
require 'some_ruby_file'
Sourcepub fn raise(exception: Class, message: &str)
pub fn raise(exception: Class, message: &str)
Raises an exception.
§Examples
§Built-in exceptions
use ruru::{Class, VM};
VM::raise(Class::from_existing("ArgumentError"), "Wrong argument");
Ruby:
raise ArgumentError, 'Wrong argument'
§Custom exceptions
use ruru::{Class, VM};
let standard_error = Class::from_existing("StandardError");
let custom_exception = Class::new("CustomException", Some(&standard_error));
VM::raise(custom_exception, "Something went wrong");
Ruby:
class CustomException < StandardError
end
raise CustomException, 'Something went wrong'
Sourcepub fn block_proc() -> Proc
pub fn block_proc() -> Proc
Converts a block given to current method to a Proc
It works similarly to def method(&block)
which converts block to Proc
§Examples
#[macro_use]
extern crate ruru;
use ruru::{Class, Object, Proc, RString, VM};
class!(Greeter);
methods!(
Greeter,
itself,
fn greet_rust_with() -> RString {
let greeting_template = VM::block_proc();
let name = RString::new("Rust").to_any_object();
greeting_template.call(vec![name]).try_convert_to::<RString>().unwrap()
}
);
fn main() {
Class::new("Greeter", None).define(|itself| {
itself.def_self("greet_rust_with", greet_rust_with);
});
}
Ruby:
class Greeter
def self.greet_rust_with(&greeting_template)
greeting_template.call('Rust')
end
end
Greeter.greet_rust_with do |name|
"Hello, #{name}!"
end
# => "Hello, Rust!"
Sourcepub fn is_block_given() -> bool
pub fn is_block_given() -> bool
Checks if a block is given to current method.
§Examples
#[macro_use] extern crate ruru;
use ruru::{Class, Fixnum, Object, VM};
class!(Calculator);
methods!(
Calculator,
itself,
fn calculate(a: Fixnum, b: Fixnum) -> Fixnum {
let a = a.unwrap();
let b = b.unwrap();
if VM::is_block_given() {
let result = VM::block_proc().call(vec![a.to_any_object(), b.to_any_object()]);
result.try_convert_to::<Fixnum>().unwrap()
} else {
Fixnum::new(a.to_i64() + b.to_i64())
}
}
);
fn main() {
Class::new("Calculator", None).define(|itself| {
itself.def("calculate", calculate);
});
}
Ruby:
class Calculator
def calculate(a, b, &block)
if block_given?
block.call(a, b)
else
a + b
end
end
end
Sourcepub fn parse_arguments(
argc: Argc,
arguments: *const AnyObject,
) -> Vec<AnyObject>
pub fn parse_arguments( argc: Argc, arguments: *const AnyObject, ) -> Vec<AnyObject>
Converts a pointer to array of AnyObject
s to Vec<AnyObject>
.
This function is a helper for callbacks, do not use it directly.
It will be moved to other struct, because it is not related to VM itself.
§Examples
use ruru::types::Argc;
use ruru::{AnyObject, Boolean, Class, Object, RString, VM};
#[no_mangle]
pub extern fn string_eq(argc: Argc, argv: *const AnyObject, itself: RString) -> Boolean {
let argv = VM::parse_arguments(argc, argv);
let other_string = argv[0].try_convert_to::<RString>().unwrap();
Boolean::new(itself.to_string() == other_string.to_string())
}
fn main() {
Class::from_existing("String").define_method("==", string_eq);
}
Sourcepub fn thread_call_without_gvl<F, R, G>(func: F, unblock_func: Option<G>) -> R
👎Deprecated since 0.9.2: Use Thread::call_without_gvl()
instead
pub fn thread_call_without_gvl<F, R, G>(func: F, unblock_func: Option<G>) -> R
Thread::call_without_gvl()
insteadRelease GVL for current thread.
Warning! Due to MRI limitations, interaction with Ruby objects is not allowed while GVL is released, it may cause unexpected behaviour. Read more at Ruby documentation
You should extract all the information from Ruby world before invoking
thread_call_without_gvl
.
GVL will be re-acquired when the closure is finished.
§Examples
#[macro_use] extern crate ruru;
use ruru::{Class, Fixnum, Object, VM};
class!(Calculator);
methods!(
Calculator,
itself,
fn heavy_computation() -> Fixnum {
let computation = || { 2 * 2 };
let unblocking_function = || {};
// release GVL for current thread until `computation` is completed
let result = VM::thread_call_without_gvl(
computation,
Some(unblocking_function)
);
// GVL is re-acquired, we can interact with Ruby-world
Fixnum::new(result)
}
);
fn main() {
Class::new("Calculator", None).define(|itself| {
itself.def("heavy_computation", heavy_computation);
});
}
pub fn thread_call_without_gvl2<F, R, G>(func: F, unblock_func: Option<G>) -> R
Thread::call_without_gvl2()
insteadpub fn thread_call_with_gvl<F, R>(func: F) -> Rwhere
F: FnOnce() -> R,
Thread::call_with_gvl()
instead