首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Rust调用内置Dyon函数?

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

Stack Overflow用户
提问于 2019-01-21 23:46:44
回答 3查看 187关注 0票数 1

我试图从Rust调用Dyon内置函数(sin):

代码语言:javascript
复制
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);
        }
    };
}

然而,我得到

代码语言:javascript
复制
Error: "Could not find function `sin`"

我需要做什么才能正确地调用这个函数?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-22 09:15:49

这两种答案都让我找到了一种解决方案,这种解决方案对两种情况都很有效:我使用了Runtime.call_str_ret并对其进行了修改,以使用来自module.find_function的任何非零结果。国际海事组织的代码实际上比运行时的原始版本更干净。我已经提交了一个已经合并的PR,所以在0.40.0之后发布的Dyon将让call_str_ret为内置函数工作。

如果您不能使用Dyon的最新版本,那么您可以从这里手动应用修补程序:https://github.com/PistonDevelopers/dyon/pull/582

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

代码语言:javascript
复制
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())
    }
}

这将允许您将原始代码编写为

代码语言:javascript
复制
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");
}

这些指纹:

代码语言:javascript
复制
Called sin - result F64(0.0, None)
Called sin_shim - result F64(0.0, None)
Error: "Could not find function `no_such`"
票数 0
EN

Stack Overflow用户

发布于 2019-01-22 00:38:44

我无法解释这里的设计决策,但是call_str_ret 只处理已加载的函数。,而不是外部功能或本质

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

代码语言:javascript
复制
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);
        }
    };
}
代码语言:javascript
复制
Called sin - result F64(0.8939966636005579, None)
票数 2
EN

Stack Overflow用户

发布于 2019-01-22 01:11:28

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

代码语言:javascript
复制
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));
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54299344

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档