0.6.0
Magnus 0.6.0 makes some breaking API changes to improve thread safety. A handful of fixes and new features are also included.
Magnus is a Rust library providing a high-level easy-to-use interface to the C API of the Ruby programming language. Magnus lets you write Ruby extension libraries (or 'gems') in Rust, or embed Ruby in your Rust program.
Thread Safety
Previous versions of Magnus have ignored thread safety in aid of getting something working, but support for threads and running Rust code outside of the Global VM Lock via rb_thread_call_without_gvl
have been common feature requests. This release prepares for the introduction of those features with some breaking API changes.
To this end all APIs that create Ruby objects have been moved to a new Ruby
handle which can only be obtained on a Ruby thread. For example RArray::new()
becomes Ruby::ary_new(&self)
(currently RArray::new()
still exists as a wrapper around Ruby::get().unwrap().ary_new()
). Default
implementations have been removed. Additionally Ruby types are no longer Send
& Sync
. An Opaque
wrapper type can be used to pass Ruby types between threads where they can only be unwrapped on a Ruby thread.
To make getting ahold of the Ruby
handle simple, functions bound as Ruby methods with method!()
and function!()
, along with the function marked with #[magnus::init]
optionally take &Ruby
as a first argument.
Other API Changes
The minimum supported Rust version is now 1.61.
The bytes-crate
and rb-sys-interop
features have been renamed to bytes
and rb-sys
respectively.
Previously all Ruby types, such as RString
, RArray
, etc Deref
'd to Value
, allowing Value
methods to be called on all Ruby types. This is no longer the case. All Value
methods have been moved to the ReprValue
trait, which is implemented by Value
and all other Ruby types.
This allows typed_data::Obj<T>
to Deref
to T
, turning typed_data::Obj
into a 'smart pointer' type that makes advanced use of wrapped data much more pleasant.
New Features
rb_assert!()
macrovalue::Lazy
lazily initialises a Ruby value so it can be assigned to astatic
- Support for subclassable wrapped Rust data via
Class::define_alloc_func
andRuby::obj_wrap_as
- The
kwargs!()
macro andKwArgs
type can be used to pass keyword arguments toReprValue::funcall
, et al. - Documentation examples for almost every function
Upgrading
If you encounter a lot of deprecation warnings when upgrading it may be easier to ignore warnings to concentrate on fixing errors, assuming your project is setup with a Rake and a 'compile' task this can be done with:
RUSTFLAGS=-Awarnings rake compile
It is also possible to ignore errors due to Value
no longer being Send + Sync
by activating the deprecated-send-sync-value
feature:
magnus = { version = "0.6", features = ["deprecated-send-sync-value"] }
This feature is intended purely as a convenience when upgrading and will be removed with the next release.
To make a Ruby type Send + Sync
wrap it with Opaque::from
. To get the Ruby type back use Ruby::get_inner()
.
Functions on Value
have moved to the ReprValue
trait, It is recommended to import this with use magnus::prelude::*
. Magnus' prelude
module only imports traits, and does so anonymously, so there is minimal chance of it causing problems.
There are no longer From<T>
/Into
implementations for Value
. In a lot of cases this can be replaced with .as_value()
. For 'wrapped' structs you will need to wrap them with Ruby::obj_wrap
first. Internally Magnus uses the IntoValue
trait, which is available publicly with use magnus::IntoValue
.
See the changelog for all the changes.
Thanks
@wfchandler for reporting issues with subclassing wrapped types.
@adampetro for implementing keyword support in funcall
, et al.