#scheme #scheme-interpreter #repl #call #run-time #bindings #guile

rust-guile

这是一个在Rust程序中提供Scheme运行时的库

4个版本

0.1.6 2021年12月15日
0.1.5 2021年3月23日

#393 in 编程语言

33 每月下载量
rust-guile-client-example 中使用

AGPL-3.0-only

530KB
19K SLoC

目录

  1. 简介
  2. 用法
    1. 函数注册
    2. 用法简述
  3. 示例
  4. 注意事项

简介

rust-guile为Rust语言中的guile提供了绑定。

使用它,你可以在Rust程序中嵌入Scheme解释器,编写在Scheme脚本中可用的Rust函数,并启动一个无需额外努力的完整Scheme repl,允许你调用Rust、C和Scheme函数。

用法

libguile的全部内容被重新导出,但这个库提供了一些提高生活质量的辅助函数和宏,使从零开始使用Scheme变得容易。

使用嵌入Scheme解释器的Rust程序将经历三个阶段

  1. 在Scheme初始化之前
  2. 在Scheme初始化之后
  3. 在Scheme启动之后

在阶段1和阶段2之间,Guile引导过程开始,并设置Scheme中使用的全局结构。

通过调用该库定义的 init_scm() 函数,您可以从阶段1进入阶段2。

在阶段2,Scheme运行时存在,您可以在Rust代码中与之交互。您可以注册函数、修改状态等。

在阶段3,Scheme repl启动并替换正在运行的Rust进程。此时,将不再执行任何Rust代码(尽管之前编译并注册到Scheme运行时的函数仍可调用!)用户将看到一个Guile Scheme repl,并可以尽情地修改。

通过调用 run_scm(argc, argv) 函数,您可以从阶段2进入阶段3。

函数注册

为了让Rust函数在Guile Scheme运行时可用,这个库提供了宏 register_void_function。您需要给这个宏两个参数:首先是一个 二进制字符串(即 &[u8]),包含您希望该函数在Scheme运行时中显示的名称。其次,是已定义的Rust函数的名称。注意,这并不是一个字符串,只需直接放入实际函数名称。您要注册的函数必须定义为 extern "C",否则Scheme不知道如何调用它,并且它必须返回一个 SCM 类型对象(该对象也由这个库导出)。

register_void_function 创建一个不接受任何参数的函数。可以定义带有参数的函数,甚至可变参数,但还没有实现有用的包装器。您可以使用 scm_c_define_gsubr 函数注册自己的函数,该函数是不安全的,需要五个参数。

  1. 函数名称作为二进制字符串,如之前所述
  2. 所需参数的数量
  3. 可选参数的数量
  4. 一个整数,它将被解释为布尔值:1 = 函数有可变参数,0 = 函数没有可变参数
  5. 函数标签(类似于宏)

用法简述

  1. 调用 init_scm()
  2. 编写您的Rust函数,并使用 register_void_function!()scm_c_define_gsubr 注册它们
  3. 调用 run_scm(argc, argv) 前往月球

示例

以下是一个示例客户端程序,它定义了一个简单的Hello World函数,然后启动了Scheme repl。您可以在Repl中运行定义的Rust函数,方法是键入 (hello-from-rust) 并按回车键。您会看到它将消息打印到Guile repl,并返回0!

use rust_guile::*;
use std::os;

extern "C" fn hello_from_rust() -> SCM {
    // an example function demonstrating that Rust functions work in Scheme
    println!("Hello from Rust!");
    unsafe {
	scm_from_int8(0)
    }
}



fn main() {
    let mut ___args = std::env::args().map(|mut arg| arg.as_mut_ptr() as *mut os::raw::c_char).collect::<Vec<*mut os::raw::c_char>>();
    let argc = ___args.len() as os::raw::c_int;
    let argv: *mut *mut os::raw::c_char = ___args.as_mut_ptr();

    init_scm();

    register_void_function!(b"hello-from-rust\0", hello_from_rust);

    run_scm(argc, argv);
}

此示例的源代码可在 https://gitlab.com/slondr/rust-guile-client-example 找到,并在crates.io上提供。

注意事项

此库对Guile 3.0有严格的要求。大多数发行版都打包了过时的Guile版本,我不知道他们为什么要这样做。如果您使用Arch,请从AUR安装Guile 3。如果您不是,请查看您的平台是否提供二进制发布版本,或者直接从源代码编译。此库要求在编译时将 libguile-3.0 放入加载路径,否则将失败。

如果您的系统使用libguile的奇怪位置,我知道有很多系统是这样的,只需从源代码重新编译此crate,pkg-config应该可以解决这个问题。如果您的系统不支持pkg-config,则此库不适合您。

最后,此库处于早期阶段,并且正在快速发展。到目前为止,我已经成功地定义了一些有趣的Rust程序并将它们加载到Scheme中,但我还没有用它做任何事情特别重大,所以您的体验可能会有很大差异。话虽如此,所有基本功能都已经具备。

欢迎提交拉取请求。

脚注

注意,此字符串遵循Scheme命名规则,而不是Rust命名规则。这意味着,例如,您可以在函数名称中使用 -

无运行时依赖项