# Using Rust inside a Crystal program

**URL:** <https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970>\
**Category:** Help & Support\
**Created:** [April 18, 2020, 10:28am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970 "2020-04-18T10:28:17Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![oren](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/oren/32/718_2.png) [@oren](https://forum.crystal-lang.org/u/oren)\
**Post date:** [April 18, 2020, 10:28am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/1 "2020-04-18T10:28:17Z")

</div>

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.

Thanks!

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 18, 2020, 11:34am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/2 "2020-04-18T11:34:40Z")

</div>

I believe it’s the same way you call C from Crystal.

Read this: [https://crystal-lang.org/reference/syntax\_and\_semantics/c\_bindings/](https://crystal-lang.org/reference/syntax_and_semantics/c_bindings/)  
And this: [https://www.greyblake.com/blog/2017-08-10-exposing-rust-library-to-c/](https://www.greyblake.com/blog/2017-08-10-exposing-rust-library-to-c/) (might be outdated, I don’t know where are the official Rust instructions for this)

Essentially, Rust can provide an API like C does. Then you link your object from file from Crystal and that’s it.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [April 18, 2020, 12:44pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/3 "2020-04-18T12:44:52Z")

</div>

> [@oren](#):
>
> when there is a need to squeeze more performance, to use call a Rust code from the Crystal program

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.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 18, 2020, 2:31pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/4 "2020-04-18T14:31:29Z")

</div>

> [@straight-shoota](#):
>
> I’m confused. How do you expect to gain more performance from Rust? Rust and Crystal should be roughly on par performance wise.

Rust has a more mature and performant multi-threading environment than Crystal currently has, which could be leveraged.

---

<div class="post-metadata">

**Author:** ![nico](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/nico/32/692_2.png) [@nico](https://forum.crystal-lang.org/u/nico)\
**Post date:** [May 4, 2020, 9:47am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/5 "2020-05-04T09:47:03Z")

</div>

Hello,

Perfs are similar.  
I use FFI to be able to use some crates in Crystal, it allows to use Rust’s echo-system.

If it helps, here’s a little POC in bulk.

```auto
├── Cargo.lock
├── Cargo.toml
├── Makefile
├── shard.yml
├── spec
│ ├── myapp_spec.cr
│ └── spec_helper.cr
├── src
│ ├── lib.rs
│ └── myapp.cr

```

Makefile

```auto
ifeq ($(shell uname),Darwin)
    EXT := dylib
else
    EXT := so
endif

all: target/debug/myrust.$(EXT)
	LIBRARY_PATH=$(PWD)/target/debug:$(LIBRARY_PATH) crystal build src/myapp.cr -o myrust
	LD_LIBRARY_PATH=./target/debug ./myrust

target/debug/myrust.$(EXT): src/lib.rs Cargo.toml
	cargo build
	cd src

clean:
	rm -rf target myrust myrust.dwarf

```

Cargo.tml

```auto
[package]
name = "crystal-rust"
version = "0.1.0"

[lib]
name = "myrust"
crate-type = ["dylib"]

```

shard.yml

```auto
name: myapp
version: 0.1.0

authors:
  - Nicolas Talle

targets:
  myapp:
    main: src/myapp.cr

crystal: 0.32.1

license: MIT

```

lib.rs

```auto
#[no_mangle]
pub extern "C" fn string() -> *const u8 {
  "Hello World\0".as_bytes().as_ptr()
}

```

myapp.cr

```crystal
@[Link("myrust")]
lib R
  fun string() : UInt8*
end

module Myapp
  VERSION = "0.1.0"

  msg = String.new(R.string())
  puts "from Rust #{msg}"
end

```

And to compile:

```auto
make

```

I use FFI (Rust) with the v0.34, but I have tested this POC only with Crystal v0.32.

To go further, callbacks help well. Pay attention to who has the ownership of the variables.

---

<div class="post-metadata">

**Author:** ![jwoertink](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jwoertink/32/50_2.png) [@jwoertink](https://forum.crystal-lang.org/u/jwoertink)\
**Post date:** [May 4, 2020, 3:17pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/6 "2020-05-04T15:17:42Z")

</div>

I love stuff like this because it’s like “mad scientist” type stuff 😆 I can’t wait to see what else you come up with this.

---

<div class="post-metadata">

**Author:** ![epipheus](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/epipheus/32/1281_2.png) [@epipheus](https://forum.crystal-lang.org/u/epipheus)\
**Post date:** [May 24, 2021, 11:48am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/7 "2021-05-24T11:48:21Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ComputerMage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/computermage/32/719_2.png) [@ComputerMage](https://forum.crystal-lang.org/u/ComputerMage)\
**Post date:** [June 8, 2021, 1:00am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/8 "2021-06-08T01:00:58Z")

</div>

Crystal can generate WASM as it uses LLVM and WASM is one of LLVM targets

---

<div class="post-metadata">

**Author:** ![jwoertink](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jwoertink/32/50_2.png) [@jwoertink](https://forum.crystal-lang.org/u/jwoertink)\
**Post date:** [June 8, 2021, 3:14pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/9 "2021-06-08T15:14:14Z")

</div>

I thought there were still issues with this because Crystal was missing a few things to be able to do this?

> [@Crystal in (possible) WASM everywhere future?](https://forum.crystal-lang.org/t/crystal-in-possible-wasm-everywhere-future/1383/20):
>
> It goes a little bit beyond that, but that’s generally the case. I’ve investigated porting Crystal to wasm32-wasi a few times over the last year and been able to get some simple programs compiling and running via various WASM runtimes. I’ve documented some of this here: [GitHub - maxfierke/crystal-wasm-tools: Tools for compiling Crystal dependencies, bindings, etc. for use with wasm](https://github.com/maxfierke/crystal-wasm-tools). I had to disable a lot of features within the stdlib to get anything working, so it’s very very rough, and not sup…

---

<div class="post-metadata">

**Author:** ![maxfierke](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/maxfierke/32/1209_2.png) [@maxfierke](https://forum.crystal-lang.org/u/maxfierke)\
**Post date:** [June 8, 2021, 3:28pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/10 "2021-06-08T15:28:31Z")

</div>

This is correct. Without the WASM ABI added to Crystal, there’s no WASM codegen support (plus allllll the other things outlined in the above post)

---

<div class="post-metadata">

**Author:** ![RespiteSage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/respitesage/32/793_2.png) [@RespiteSage](https://forum.crystal-lang.org/u/RespiteSage)\
**Post date:** [June 8, 2021, 4:09pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/11 "2021-06-08T16:09:16Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![maxfierke](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/maxfierke/32/1209_2.png) [@maxfierke](https://forum.crystal-lang.org/u/maxfierke)\
**Post date:** [June 8, 2021, 5:43pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/12 "2021-06-08T17:43:19Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![paulocoghi](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/paulocoghi/32/1429_2.png) [@paulocoghi](https://forum.crystal-lang.org/u/paulocoghi)\
**Post date:** [August 3, 2023, 10:12am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/13 "2023-08-03T10:12:00Z")

</div>

In our scenario, one reason is to embed a [HTTP/3 proxy library](https://github.com/junkurihara/rust-rpxy) made in Rust. Currently, AFAIK there is no HTTP/3 library available in Crystal.

Being able to use Rust inside Crystal allows us to benefit from the bigger library ecosystem, like the HTTP/3 library from the example above.

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [August 4, 2023, 5:10am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/14 "2023-08-04T05:10:39Z")

</div>

Recently, the Ruby bundler allows you to select the Rust extension when generating a Gem from a template.

```auto
bundle gem --ext rust foobar

```

```auto
├── Cargo.toml
├── ext
│ └── foobar
│ ├── Cargo.toml
│ ├── extconf.rb
│ └── src
│ └── lib.rs

```

ext/foobar/Cargo.toml

```toml
[package]
name = "foobar"
version = "0.1.0"
edition = "2021"
authors = ["kojix2 <dummy@mail.com>"]
license = "MIT"
publish = false

[lib]
crate-type = ["cdylib"]

[dependencies]
magnus = { version = "0.4" }

```

ext/foobar/extconf.rb

```auto
# frozen_string_literal: true

require "mkmf"
require "rb_sys/mkmf"

create_rust_makefile("foobar/foobar")

```

lib.rs

```auto
use magnus::{define_module, function, prelude::*, Error};

fn hello(subject: String) -> String {
    format!("Hello from Rust, {}!", subject)
}

#[magnus::init]
fn init() -> Result<(), Error> {
    let module = define_module("Foobar")?;
    module.define_singleton_method("hello", function!(hello, 1))?;
    Ok(())
}

```

In the case of Ruby, it appears that [rb-sys](https://github.com/oxidize-rb/rb-sys) generates the primitive bindings and [magnus](https://github.com/matsadler/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](https://github.com/ankane/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.

---

<div class="post-metadata">

**Author:** ![kojix2](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/kojix2/32/1583_2.png) [@kojix2](https://forum.crystal-lang.org/u/kojix2)\
**Post date:** [August 9, 2023, 7:58am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/15 "2023-08-09T07:58:36Z")

</div>

I am creating a Crystal binding for [tiktoken-rs](https://github.com/zurawiki/tiktoken-rs) using the method suggested by @nico. I have confirmed that it does indeed work.

[tiktoken-cr](https://github.com/kojix2/tiktoken-cr)

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.

[tiktoken-c](https://github.com/kojix2/tiktoken-c)

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.

---

<div class="post-metadata">

**Author:** ![botato](https://avatars.discourse-cdn.com/v4/letter/b/a88e57/32.png) [@botato](https://forum.crystal-lang.org/u/botato)\
**Post date:** [August 9, 2023, 6:02pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/16 "2023-08-09T18:02:08Z")

</div>

There is crystal bindings to a C quic/HTTP/3 library:

> **[GitHub - iv-org/lsquic.cr: Crystal bindings to LiteSpeed QUIC](https://github.com/iv-org/lsquic.cr)**
>
> Crystal bindings to LiteSpeed QUIC. Contribute to iv-org/lsquic.cr development by creating an account on GitHub.

I have not used it, I don’t know what state it’s in, but it looks like it is used by Invidious so I assume it’s decent

---

<div class="post-metadata">

**Author:** ![stellarpower](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/stellarpower/32/2072_2.png) [@stellarpower](https://forum.crystal-lang.org/u/stellarpower)\
**Post date:** [October 31, 2023, 1:48am UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/17 "2023-10-31T01:48:08Z")

</div>

Is there any chance we could do something similar to what magnus is doing, probably using the macro system? I have seen [Bindgen](https://github.com/Papierkorb/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.

---

<div class="post-metadata">

**Author:** ![lautan](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@lautan](https://forum.crystal-lang.org/u/lautan)\
**Post date:** [January 12, 2024, 8:03pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/18 "2024-01-12T20:03:01Z")

</div>

That would be amazing. I would like something similar to this. There are many rust packages that can be used.

---

<div class="post-metadata">

**Author:** ![lautan](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@lautan](https://forum.crystal-lang.org/u/lautan)\
**Post date:** [June 10, 2024, 11:12pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/19 "2024-06-10T23:12:53Z")

</div>

I ended up creating a Crystal library that wraps whichlang (written in Rust). You can find it here as an example: [GitHub - bendangelo/whichlang.cr: Crystal bindings for Whichlang language detection library](https://github.com/bendangelo/whichlang.cr)

The reason I did this was to piggyback off of Whichlang and give access to this functionality in Crystal codebases.

---

<div class="post-metadata">

**Author:** ![lautan](https://avatars.discourse-cdn.com/v4/letter/l/3be4f8/32.png) [@lautan](https://forum.crystal-lang.org/u/lautan)\
**Post date:** [August 18, 2024, 3:20pm UTC](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970/20 "2024-08-18T15:20:48Z")

</div>

Because this shows up on search results. I want to give an updated response. I’ve also successfully integrated crystal with a rust library called tantivy. You can see my repo for examples on how this was done: [bendangelo/tantivy.cr: Provides Crystal bindings for Tantivy. The fast full-text search engine library written in Rust. - Codeberg.org](https://codeberg.org/bendangelo/tantivy.cr)

This example has more complex types, like arrays and pointers.

[Next page](https://forum.crystal-lang.org/t/using-rust-inside-a-crystal-program/1970.md?page=2)
