Rust Guide#

Note

The Rust support is currently in an experimental stage.

This guide demonstrates how to use TVM FFI from Rust applications.

Installation#

Prerequisites#

The Rust support depends on libtvm_ffi. First, install the tvm-ffi Python package:

pip install -v -e .

Confirm that tvm-ffi-config is available:

tvm-ffi-config --libdir

Adding to Your Project#

Add to your Cargo.toml:

[dependencies]
tvm-ffi = { path = "path/to/tvm-ffi/rust/tvm-ffi" }

For published versions (when available):

[dependencies]
tvm-ffi = "0.1.0-alpha.0"

Environment Setup#

Set the library path so libtvm_ffi can be found at runtime:

export LD_LIBRARY_PATH=$(tvm-ffi-config --libdir):$LD_LIBRARY_PATH

Basic Usage#

Loading a Module#

Load a compiled TVM FFI module and call its functions:

use tvm_ffi::{Module, Result};

fn main() -> Result<()> {
    // Load compiled module
    let module = Module::load_from_file("build/add_one_cpu.so")?;

    // Get function by name
    let add_fn = module.get_function("add_one_cpu")?;

    Ok(())
}

Working with Tensors#

Create and manipulate tensors:

use tvm_ffi::Tensor;

// Create a tensor from a slice
let data = vec![1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
let tensor = Tensor::from_slice(&data, &[2, 3])?;

Calling Functions#

Call functions with tensors:

use tvm_ffi::{Module, Tensor, Result};

fn run_example() -> Result<()> {
    let module = Module::load_from_file("build/add_one_cpu.so")?;
    let func = module.get_function("add_one_cpu")?;

    // Create input and output tensors
    let input = Tensor::from_slice(&[1.0f32, 2.0, 3.0, 4.0], &[4])?;
    let output = Tensor::from_slice(&[0.0f32; 4], &[4])?;

    // Call function
    func.call_tuple((&input, &output))?;

    Ok(())
}

Advanced Topics#

Global Functions#

Register and access global functions:

use tvm_ffi::Function;

// Get global function
let func = Function::get_global("my_function")?;

// Register a new global function
let my_func = Function::from_packed(|args: &[AnyView]| -> Result<Any> {
    // Function implementation
    Ok(Any::default())
});
Function::register_global("my_custom_func", my_func)?;

Type-Erased Functions#

Create functions from Rust closures:

use tvm_ffi::{Function, Any, AnyView, Result};

// From packed closure
let func = Function::from_packed(|args: &[AnyView]| -> Result<Any> {
    // Process args and return result
    Ok(Any::default())
});

// From typed closure
let typed_func = Function::from_typed(|x: i64, y: i64| -> Result<i64> {
    Ok(x + y)
});

Error Handling#

TVM FFI uses standard Rust Result types:

use tvm_ffi::{Error, Module, Result, VALUE_ERROR};

fn may_fail(value: i32) -> Result<()> {
    // Operations that may fail
    let module = Module::load_from_file("path.so")?;

    // Custom errors
    if value < 0 {
        return Err(Error::new(
            VALUE_ERROR,
            "Value must be non-negative",
            ""
        ));
    }

    Ok(())
}

Examples#

The repository includes a complete example in rust/tvm-ffi/examples/load_library.rs.

Run it with:

cd rust
cargo run --example load_library --features example

Building the Workspace#

Build the entire Rust workspace:

cd rust
cargo build

Run tests:

cargo test

API Reference#

For detailed API documentation, see the Rust API Reference.