Select Page

You are part of a team that is programming in RUST.

The team understands the benefits of RUST in the entirety. Your team is aware that Rust is blazingly fast and memory efficient. They are now boldly refactoring the application thanks to the type system and ownership model.

One of the use-cases demands you to write an algorithm. A considerable part of the algorithm is already available in your legacy C codebase and is proved to be working fine.

Will you leverage the algorithm or will you re-write? What will be your strategy?

Suggested Solution

I recommend to first look for options to leverage the algorithm written in C through the Foreign Function Interface route of Rust. If reliability and maintainability of the legacy code is an issue, I still recommend strangulation or progressive re-writing of the algorithm in rust rather than complete re-writing of the entire algorithm.

A complete working Example of FFI

mymatch.c – The Legacy code

For the sake of simplicity let us assume that you want to invoke the add_numbers function written in mymath.c from your RUST code. LOL, what a fantastic algorithm !!!!

float add_numbers(float n1, float n2) {
    return n1+n2;
}   

float sub_numbers(float n1, float n2) {
    return n1-n2;
}

Write a CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(calc C)
add_library(mymath STATIC mymath.c)
install(TARGETS mymath DESTINATION .)

main.rs.

The rust code that is interested in invoking, the powerful, add_numbers function of mymath.c.

#[link (name="mymath", kind="static")]
extern "C" {
    fn add_numbers(num1:f32,num2:f32) -> f32;
}
fn main() {
    println!("Hello, world!");
    let res = unsafe{ add_numbers(10.2, 10.3)};
    println!("The result is {}",res);
}

Watch the extern block in the aforesaid code. The block houses the list of all the functions you want to link into your current main.rs. The #[link instructs the linker to use the mymath.c to resolve the symbols.

Now you can invoke the add_numbers from the main(). Of course, you should fence the function invocation with the unsafe block.

Finally, you should write a build.rs to instruct the cargo to build mymath.c and make it available to link with main.rs

extern crate cmake;

use cmake::Config;

fn main() {
    let _dst = Config::new("calc").build();
    println!("cargo:rustc-link-search=native={}",_dst.display());
    println!("cargo:rustc-link-lib=static=mymath");
}

That’s all.