WolframResearch / wolfram-library-link-rs

Safe, efficient, and ergonomic bindings to Wolfram LibraryLink and the Wolfram Language
Apache License 2.0
52 stars 5 forks source link

How to return non-LibraryDataType? #30

Closed oovm closed 2 years ago

oovm commented 2 years ago

For example I have a rust type:

struct Point {
    x: f64,
    y: f64
}

I want to return a wolfram type:

Point[{x, y}]
ConnorGray commented 2 years ago

@oovm thank you for filing an issue about this. I've written a new piece of documentation that I hope will answer your question, and be useful to others with similar questions:

How To: Convert Between Rust and Wolfram Types

Please let me know if this resource answers your question, or if you have additional questions or feedback. Thanks!

oovm commented 2 years ago

What's the best way to handle a function may fail?

I mean some function return Result<T>, for example if str::parse fails, what should I return, and how to show the error log?

ConnorGray commented 2 years ago

What's the best way to handle a function may fail?

Depending on your use case, using unwrap() or expect() on the Result and letting a panic occur may be okay. Rust LibraryLink functions exported using #[export(wstp)] will automatically return a Failure[..] object to the Wolfram Language with information about the panic.

If you want more control over the expression that gets returned, you could construct a Failure[..] object manually, e.g.:

use wolfram_library_link::{export, expr::{Expr, Symbol}};

#[export(wstp)]
fn string_to_integer(args: Vec<Expr>) -> Expr {
    assert_eq!(args.len(), 1, "expected 1 argument");
    let arg: &str = args[0].try_as_str().expect("expected String argument");

    match i64::from_str(arg) {
        Ok(int) => Expr::from(int),
        // Convert the error into a Failure[..] expression.
        Err(error) => Expr::normal(Symbol::new("System`Failure"), vec![
            Expr::string("StringToIntegerConversion"),
            Expr::normal(Symbol::new("System`Association"), vec![
                Expr::rule("MessageTemplate", Expr::string(format!("conversion of {:?} to integer failed: {}", arg, error))),
            ])
        ])
    }
}

and use it from Wolfram:

stringToInteger = LibraryFunctionLoad["...", "string_to_integer", LinkObject, LinkObject];

stringToInteger["5"]  (* Returns 5 *)

stringToInteger["Not A Number"] (* Returns Failure["StringToIntegerConversion", ...] *)