It will be nice to write a Crystal program and when there is a need to squeeze more performance, to use call a Rust code from the Crystal program. In addition it will just be a fun way to learn both languages. Can someone share a step by step instructions for doing it?
Google search sent me to this forum but it didn’t give me concrete steps I can follow.
I’m confused. How do you expect to gain more performance from Rust? Rust and Crystal should be roughly on par performance wise. Both compile to a LLVM backend, so even the optimizations are pretty similar. There are some differences in the runtimes, but I’m not aware that makes a big difference. Many benchmarks show Rust and Crystal performing pretty similar. Even if one had a slight edge over the other, it would most likely not justify the overhead for switching to the other.
This could still be a fun endevour, I just don’t think this makes sense when you’re looking for performance improvement.
There is plenty reason to do this. For example, Rust can compile to WASM and Crystal cannot. Moreover. Rust has many blockchain SDKs whereas Crystal none. Yet Crystal can be used for a lot of the logic and interop. Rails has Helix to do this. Doing this with Crystal would be nice.
I know that garbage collection was a proposal on WASM a year or two ago; has that been officially included as part of the standard (/ is it available in the LLVM implementation)? It seems like that would be a major blocker (in addition to threads), and even then we’d probably need to write something to fit that standard (or use someone else’s implementation of WASM libgc).
@RespiteSage Please see the above linked post. Would be happy to continue discussion about WASM there, but probably not relevant further in this post about using Rust alongside Crystal.
In the case of Ruby, it appears that rb-sys generates the primitive bindings and magnus does the type conversion between Ruby and Rust. (I am not familiar with this at all) An example of actual use is polars-ruby.
How can I do this for the Crystal language? I guess it would be something like this.
Create a thin wrapper library on the target Rust library that implements functions with primitive types as arguments that can be called in C. Set #[no_mangle] and pub extern "C".
Generate the shared library in a Makefile. Link objects from Crystal.
But the problem is that I need to write a wrapper for tiktoken-rs. The types used in Rust structures and the types used in Rust functions are not compatible with C. So you need to write your own C API before trying to generate a shared object.
In Python and Ruby, attributes are added to Rust’s (struct + trait) to automatically convert types and automatically generate bindings. But such approaches are not compatible across languages. It would be nice if there was a common way to easily call Rust from other languages.
Is there any chance we could do something similar to what magnus is doing, probably using the macro system? I have seen Bindgen consume C++ APIs at build time, which is pretty awesome. Even if not trivial, if that is possible, I feel like wrapping a Crate ought to be less complicated.