Crystal integration with Rust

Hi, I had the bright idea to integrate Crystal with Rust, which is more less worked out, but there is one thing which does not seem to work, Arrays.

Since Rust can compile to C compatible code, like this

#[no_mangle]
pub extern "C" fn rust_function() {
    println!("Hello from Rust");
}

#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn rust_sum(a: Vec<i32>) -> i32 {
    let mut sum = 0;
    for item in a {
        sum += item;
    }
    sum
}

and Crystal can load C libs like this

module Rshost
  VERSION = "0.1.0"

  @[Link(ldflags: "#{__DIR__}/../../embed/target/release/libembed.so")]
  lib MyDylib
    fun rust_function : Void
    fun rust_add(a: Int32, b: Int32) : Int32
    fun rust_sum(a: Pointer(Int32)) : Int32
  end

  MyDylib.rust_function
  puts MyDylib.rust_add(2, 3)
  puts MyDylib.rust_sum([1,2])
end

the only problem is with the last function the rust_sum is not working as expected, if I mean expected to work at all :D The error what I’m getting is the following

imre@DESKTOP-1JK127M:/mnt/d/Documents/Git/rs-cr-magic/rshost$ crystal run src/rshost.cr 
Hello from Rust
5
Invalid memory access (signal 11) at address 0x28d8bca3c
[0x7fe58d64d6c6] *CallStack::print_backtrace:Int32 +118
[0x7fe58d640f80] __crystal_sigfault_handler +192
[0x7fe58ca92890] ???
[0x7fe58cf5ddd0] rust_sum +176
[0x7fe58d633a2c] __crystal_main +1628
[0x7fe58d68e286] *Crystal::main_user_code<Int32, Pointer(Pointer(UInt8))>:Nil +6
[0x7fe58d68e1e9] *Crystal::main<Int32, Pointer(Pointer(UInt8))>:Int32 +41
[0x7fe58d63e466] main +6
[0x7fe58c011b97] __libc_start_main +231
[0x7fe58d6332ea] _start +42
[0x0] ???

It’s totally possible, that my Rust is in fault, but maybe someone could help me out.

It won’t work this way. Vector in Rust is a much more complex construct than just pointer. Code on a Rust side should take not a vector, but a raw pointer and number of elements, then (unsafely) construct a vector from them.

Well, I don’t know Rust. Maybe you should construct slice not vector, and maybe it’s not unsafe as long as calling contract holds.
But general idea is that you should pass pointer and size.

yes, after some digging around, you are probably right, I came to the same conclusion too. I will try it out, when I have some free time, and probably try to include in a Python code, I’m more proficient with that, thanks for the help

I successfully updated the Rust code, like this, now it works as expected. Thanks for the help. :slight_smile:

#[no_mangle]
    pub extern "C" fn rust_sum(ptr: *const i32, size: usize) -> i32 {
        assert!(!ptr.is_null());
        let arr = unsafe {
            slice::from_raw_parts(ptr, size)
        };
        let mut sum = 0;
        for item in arr {
            sum += item;
        }
        sum
    }
2 Likes

Hello,

I’m looking for the opposite, call Crystal from Rust code.
Do you have an example please?

I don’t think crystal can generate .so library file currently.

Ok thanks.
It would have been practical and fun to develop in Crystal some time-consuming parts in Rust

The answer is in my previous message and in your question.

It would have been practical and fun to develop in Crystal some time-consuming parts in Rust

higher abstraction to extend a lower one

Also, because I want learn Crystal not Lua…

Crystal is statically typed, compiled and not a scripting langage like Lua. Using Crystal to save time on certain features (ORM, data processing, …) would have been a good entry point (without too much performance penalty) .

Because you have some time to loss. You arg, I answer you only by politeness…

It was not for Rust that I intended to do that, just for the convenience of developing certain features in Crystal and to learn Crystal in an existing project in Rust.

anykeyh already answered my question, so I dropped this idea.

Happy coding

On the higher safety provided by rust I agree. But performance wise, there should not be much difference between Crystal and Rust. They both heavily rely an optimizations provided by LLVM. Do you have any supporting evidence that Rust could provide a relevant speed improvement?

Anyways, regarding the original question: Technically, you can build C libraries with Crystal and link them from other languages. From the language itself, this is not an issue. The practical problems come from the standard library, which is built around a global runtime providing fibers, GC etc. which might conflict with other runtimes when it’s only used as a library.

Thank you for the clarification. I understand the risk. Even if It sounds tricky, glad to know that it is not impossible.

Is there anything planned about that?