Search code examples
ffidylibcrystal-lang

How to call functions from a dylib using Crystal?


I wish to call the various functions defined in a Rust dylib using Crystal. I've gone through the manual, but I was not able to understand it. How do I properly include and call this dylib? Am I using the CLI flags wrong?

Here's the Crystal code:

@[Link("libmy_dylib")]
lib MyDylib
  # In C: double cos(double x)
  # In Rust: print_number(x:i32) 
  fun print_number(value : Int32)
end

MyDylib.print_number(10)

I compiled a dylib using this repo. The code compiles fine to a libmy_dylib.dylib:

extern crate libc;

use libc::uint32_t;

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

#[no_mangle]
pub extern "C" fn print_number(x: i32) {
    println!("x is: {}", x);
}

#[no_mangle]
pub extern "C" fn addition(a: uint32_t, b: uint32_t) -> uint32_t {
    let c = a + b;
    println!("Sum : {}", c);

    return a + b;
}

#[allow(dead_code)]
pub extern "C" fn fix_linking_when_not_using_stdlib() {
    panic!()
}

Solution

  • You need to specify the dylib with an absolute path, and pass it through ldflags. For instance, the following Rust file

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

    that compiles to libmy_dylib.dylib can be linked like this:

    @[Link(ldflags: "/absolute/path/to/libmy_dylib.dylib")]
    lib MyDylib
      fun hello : Void
    end
    
    MyDylib.hello
    

    And the program will compile to print "Hello from Rust!"