繁体   English   中英

如何从Rust调用内置的Dyon函数?

[英]How do I call a built-in Dyon function from Rust?

我正在尝试从Rust调用Dyon内置函数( sin ):

use dyon::{Module, Runtime, Variable};
use std::sync::Arc;

fn main() {
    let mut dyon_runtime = Runtime::new();
    let module = Module::new();
    let dyon_module = Arc::new(module);
    let v = dyon_runtime.call_str_ret("sin", &[Variable::f64(0.0)], &dyon_module);
    match v {
        Err(e) => {
            eprintln!("Error: {:?}", e);
        }
        Ok(v) => {
            println!("Called sin - result {:?}", v);
        }
    };
}

但是,我得到

Error: "Could not find function `sin`"

我需要怎么做才能正确调用此函数?

我在这里无法解释设计决策,但是call_str_ret 仅处理已加载的 函数 ,而不处理外部函数或内部函数

作为一种解决方法,您可以加载一个小的shim函数,该函数只是调用适当的函数:

use dyon::{Module, Runtime, Variable};
use std::sync::Arc;

fn main() {
    let mut dyon_runtime = Runtime::new();
    let mut module = Module::new();

    let shim = Arc::new("do_it(x) = sin(x)".into());
    dyon::load_str("main.rs", shim, &mut module).expect("Unable to load shim function");
    let dyon_module = Arc::new(module);

    let v = dyon_runtime.call_str_ret("do_it", &[Variable::f64(90.0)], &dyon_module);
    match v {
        Err(e) => {
            eprintln!("Error: {:?}", e);
        }
        Ok(v) => {
            println!("Called sin - result {:?}", v);
        }
    };
}
Called sin - result F64(0.8939966636005579, None)

call_str()只关心一种类型的函数调用。 我不知道他们为什么要这样做,但是一种解决方案是自己做:

use dyon::{ast, Module, Runtime, Variable};
use range::Range;
use std::cell::Cell;
use std::sync::Arc;

fn main() {
    let mut dyon_runtime = Runtime::new();
    let module = Module::new();

    let name: Arc<String> = Arc::new("sin".into());
    let f_index = Cell::new(module.find_function(&name, 0));
    let args = vec![ast::Expression::Variable(Box::new((
        Range::empty(0),
        Variable::F64(1.0, None),
    )))];
    let call = ast::Call {
        alias: None,
        name,
        f_index,
        args,
        custom_source: None,
        source_range: Range::empty(0),
    };
    let dyon_module = Arc::new(module);
    println!("{:?}", dyon_runtime.call(&call, &dyon_module));
}

其他两个答案都导致我找到了一种在两种情况下都可以正常使用的解决方案:我将Runtime.call_str_ret修改为使用module.find_function所有非结果。 IMO代码实际上比运行时中的原始版本干净。 我已经为此提交了一个PR,该PR已被合并,因此Dyon在0.40.0之后的版本将具有call_str_ret用于内置函数。


如果您不能使用更新版本的Dyon,则可以从以下位置手动应用补丁: https : //github.com/PistonDevelopers/dyon/pull/582

或者,您也可以使用自己的call_str_ret版本,如下所示:

use dyon::{Module, Runtime, Variable};
use std::sync::Arc;

extern crate range;

/// Call function by name, returning a value.
pub fn call_str_ret_ex(
    runtime:&mut Runtime,
    function: &str,
    args: &[Variable],
    module: &Arc<Module>
) -> Result<Variable, String> {
    use std::cell::Cell;
    use range::Range;
    use dyon::FnIndex;
    use dyon::runtime::Flow;
    use dyon::ast;

    let name: Arc<String> = Arc::new(function.into());
    let fn_index = module.find_function(&name, 0);
    if let FnIndex::None = fn_index {
        return Err(format!("Could not find function `{}`",function))
    }

    let call = ast::Call {
        alias: None,
        name: name.clone(),
        f_index: Cell::new(fn_index),
        args: args.iter()
                .map(|arg| ast::Expression::Variable(Box::new((
                            Range::empty(0), arg.clone()))))
                .collect(),
        custom_source: None,
        source_range: Range::empty(0),
    };
    match runtime.call(&call, &module) {
        Ok((Some(val), Flow::Continue)) => Ok(val),
        Err(err) => Err(err),
        _ => Err("Error during call".to_owned())
    }
}

这将使您将原始代码编写为

def test_dyon_fn(
    dyon_runtime: &mut Runtime
    module: &Module,
    fn: &str,
)
    let v = call_str_ret_ex(&mut dyon_runtime, fn, &[Variable::f64(0.0)], &dyon_module);
match v {
    Err(e) => {
        eprintln!("Error: {:?}", e);
    }
    Ok(v) => {
        println!("Called {:?}  - result {:?}", fn, v);
    }
};

fn main() {
    let mut dyon_runtime = Runtime::new();
    let mut module = Module::new();
    let shim = Arc::new("sin_shim(x) = sin(x)".into());
    dyon::load_str("main.rs", shim, &mut module).expect("Unable to load shim function");
    let dyon_module = Arc::new(module);

    test_dyon_fn(&mut dyon_runtime, &dyon_module, "sin");
    test_dyon_fn(&mut dyon_runtime, &dyon_module, "sin_shim");
    test_dyon_fn(&mut dyon_runtime, &dyon_module, "no_such");
}

打印:

Called sin - result F64(0.0, None)
Called sin_shim - result F64(0.0, None)
Error: "Could not find function `no_such`"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM