本文为转载摘要,完整版请移步:
https://mp.weixin.qq.com/s/YT_HNFDCQ_IyocvBkRNJnA
以下为译文:
大约一年前,我发布了一个名为inline-python(https://crates.io/crates/inline-python)的Rust类库,它允许大家使用python!{ .. }宏轻松地将一些Python混合到Rust代码中。在本系列中,我将从头展示开发此类库的过程。
-1-
预览
如果不熟悉inline-python类库,你可以执行以下操作:
fn main() {
let who = "world";
let n = 5;
python! {
for i in range('n):
print(i, "Hello", 'who)
print("Goodbye")
}
}
它允许你将Python代码直接嵌入Rust代码行之间,甚至直接在Python代码中使用Rust变量。
我们将从一个比这个简单得多的案例开始,然后逐步努力以达到这个结果(甚至更多!)。
-2-
运行Python代码
首先,让我们看一下如何在Rust中运行Python代码。让我们尝试使第一个简单的示例生效:
fn main() {
println!("Hello ...");
run_python("print(\"... World!\")");
}
我们可以使用std::process::命令来运行python可执行文件并传递python代码,从而实现run_python,但如果我们希望能够定义和读回Python变量,那么最好从使用PyO3库开始。
PyO3为我们提供了Python的Rust绑定。它很好地包装了Python C API,使我们可以直接在Rust中与各种Python对象交互。(甚至在Rust中编写Python库,但这是另一个主题。)
它的Python::run 功能完全符合我们的需求。它将Python代码作为&str,并允许我们使用两个可选的PyDicts 来定义范围内的任何变量。让我们试一试吧:
fn run_python(code: &str) {
let py = pyo3::Python::acquire_gil(); // Acquire the 'global interpreter lock', as Python is not thread-safe.
py.python().run(code, None, None).unwrap(); // No locals, no globals.
}
$ cargo run
Compiling scratchpad v0.1.0
Finished dev [unoptimized + debuginfo] target(s) in 0.29s
Running `target/debug/scratchpad`
Hello ...
... World!
看,这就成功了!
-3-
基于规则的宏
在字符串中编写Python不是最便捷的方法,所以我们尝试改进它。宏允许我们在Rust中自定义语法,所以让我们尝试一下:
fn main() {
println!("Hello ...");
python! {
print("... World!")
}
}
宏通常是使用macro_rules!进行定义,您可以基于标记和表达式之类的内容使用高级“查找和替换”规则来定义宏。(有关macro_rules!的介绍请参见Rust Book中有关宏的章节,有关Rust宏所有的细节都可以在《Rust宏的小书》中找到。)
完整版请移步:https://mp.weixin.qq.com/s/YT_HNFDCQ_IyocvBkRNJnA
领取专属 10元无门槛券
私享最新 技术干货