Work with tensors
Inspect model inputs, check a backend, and pass raw tensors.
Use your own .slab model and a runtime license. Model files carry their input sizes, preprocessing, labels, and backend preferences.
tensors.cplus
C+ setup →// Inspect a model, check it fits a backend, then run it on raw tensors.
//
// Use this path for models whose inputs are not images, or when the app
// prepares the input tensor itself.
import "stdlib/io" as io;
import "stdlib/env" as env;
import "stdlib/fs" as fs;
import "stdlib/result" as result;
import "stdlib/option" as option;
import "stdlib/vec" as vec;
import "ffi/api" as slab;
fn print_shape(ref s: slab::Session, idx: i32, input: bool) {
for a in 0..6 {
let d = if input { s.input_dim(idx, a) } else { s.output_dim(idx, a) };
if d <= 0i64 { break; }
io::print(if a == 0 { " " } else { "x" });
io::print("${d}");
}
io::println("");
}
fn main() -> i32 {
var cfg = slab::Config::new();
cfg.set_models_dir("models");
guard let option::Option::Some(path) = env::var("SLAB_RUNTIME_LICENSE_FILE") else { return 1; };
guard let result::Result::Ok(token) = fs::read_to_string(path.view()) else { return 1; };
if !cfg.set_runtime_license(token.view()) { return 1; }
var session = slab::Session::new(cfg);
// Inspect reads the model's description without loading its weights.
if !session.inspect("classifier.slab") {
io::eprintln("Cannot inspect: ${session.error_message()}");
return 1;
}
for i in 0..session.input_count() {
io::print("input ${session.input_name(i)}:");
print_shape(session, i, true);
}
for i in 0..session.output_count() {
io::print("output ${session.output_name(i)}:");
print_shape(session, i, false);
}
io::println("estimated memory: ${session.estimated_memory_bytes()} bytes");
if !session.check_backend(slab::BACKEND_GPU) {
io::println("GPU cannot run it: ${session.error_message()}");
}
if !session.open("classifier.slab") {
io::eprintln("Cannot open: ${session.error_message()}");
return 1;
}
// Build an input tensor of the declared size (here, all zeros).
var count: usize = 1;
for a in 0..6 {
let d = session.input_dim(0, a);
if d <= 0i64 { break; }
count = count * (d as usize);
}
var data = vec::with_capacity::[f32](count);
for i in 0..(count as i32) { let _ = data.append(0.0f32); }
guard let option::Option::Some(ptr) = data.at_ptr(0) else { return 1; };
var inp = slab::Input::new();
var out = slab::Output::new();
// copy = false: Slab reads the buffer during run() only.
if !inp.set_named_f32(session.input_name(0), ptr, count, false) {
io::eprintln("Input rejected");
return 1;
}
if !session.run(inp, out) {
io::eprintln("Run failed: ${session.error_message()}");
return 1;
}
let y = out.f32_ptr(0);
io::println("output 0: ${out.f32_len(0)} values, first ${y[0]}, on ${slab::backend_name(out.backend_used())}");
return 0;
}