bvssvni/rust-idris-fs

Calling a simple function written in Rust from Idris

bvssvni opened this issue · 0 comments

To call Rust from Idris, you need to generate IR code to make it freestanding (not depending on runtime).
IR code is an intermediate language for LLVM which can then be compiled to a ".o" file.
In addition you need to write a C header file manually so Idris can link to a ".o" and a ".h" file.
Idris does not know it is calling Rust, so the type system is limited to C.

Here is the Idris code, in a file Main.idr.

module Main

%include C "idrisfs.h"
%link C "idrisfs.o"

getSizeInt : IO Int
getSizeInt = mkForeign (FFun "sizeof_int" [] FInt)

main : IO ()
main = do
  x <- getSizeInt
  putStrLn (show x)

Here is the Rust code, in a file lib.rs:

#![crate_id = "idrisfs"]
#![deny(missing_doc)]

//! Documentation goes here.

/// Returns the number of bytes in an int.
#[no_mangle]
pub extern "C" fn sizeof_int() -> int {
    std::mem::size_of::<int>() as int
}

Here is the C header in a file idrisfs.h:

#ifndef IDRISFS
#define IDRISFS

int sizeof_int(void);

#endif

Command for generating IR:

rustc lib.rs -o idrisfs.ll --crate-type=lib --emit=ir

In order to use llc you need to add it to the PATH variable.
On OSX this is done to the .bash_profile file in the ~ directory.
On my system this becomes:

export PATH="/usr/local/Cellar/llvm/3.4/bin/":$PATH

Then you can execute the last command:

llc idrisfs.ll -o idrisfs.o -filetype=obj

To run, you can do idris Main.idr and then :exec.
It should print 8.