在运行时使用C,我可以:
在Rust中可能有类似的事情吗?
特别是我想使用代数数据类型,因此使用Rust的C功能子集是不够的。
答案 0 :(得分:14)
还没有,正式的,虽然它应该至少可能没有太多的黑客攻击。最大的障碍是图书馆还没有动态加载的能力。 这是一个使其有效的潜在策略(在Rust的传入分支上)。
#[no_mangle]
标记要呼叫的功能。这应该(我没有尝试过)产生一个未编码的符号名称,因此很容易找到。sys::Closure
中定义)。Rust还有一个经过最低限度测试的JIT,可用于此类事情,但它有一些重大错误。
答案 1 :(得分:2)
可能还有其他可能的解决方案,但是,我最近使用了以下解决方案,它对于我的特定要求一直很好。
希望它对您也很有用,或者它可以为您提供起点,以寻求更复杂,更强大的解决方案。
main.rs
Prelude> :{
Prelude| fact :: Int -> Int
Prelude| fact n = product [1..n]
Prelude| :}
Cargo.toml
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::process::Command;
use libloading::{Library, Symbol};
/// signature of function which should be called from plugin
type AddFunc = unsafe fn(isize, isize) -> isize;
/// Create a plugin file at runtime which will be converted to shared library
fn write_file() -> std::io::Result<()> {
let mut file = File::create("plugin.rs")?;
file.write_all(b"fn main() {\n")?;
file.write_all(b"\t#[no_mangle]\n")?;
file.write_all(b"\tpub extern \"C\" fn add(a: isize, b: isize) -> isize {\n")?;
file.write_all(b"\t\ta + b\n")?;
file.write_all(b"\t}\n")?;
file.write_all(b"}\n")?;
Ok(())
}
/// compile plugin code file to shared library
/// todo 1) should allow to pass file path.
/// 2) should return path to generated shared library
fn compile_file() {
let mut compile_file = Command::new("cmd");
compile_file.args(&["/C", "rustc", "--crate-type", "cdylib", "plugin.rs"]).status().expect("process failed to execute");
}
/// call function from shared library
/// todo suffix should be selected based on OS.
fn call_plugin(a: isize, b: isize) -> isize {
let lib = Library::new("plugin.dll").unwrap();
unsafe {
let func: Symbol<AddFunc> = lib.get(b"add").unwrap();
let answer = func(a, b);
answer
}
}
fn main(){
let args: Vec<String> = env::args().collect();
if args.len() == 3 {
write_file();
compile_file();
/// get argument from commandline to pass to function
let a: isize = args[1].trim().parse().expect("number required");
let b: isize = args[2].trim().parse().expect("number required");
println!("{}+{}:{}",a,b,call_plugin(a,b));
}
else {
println!("USAGE: main.exe NUM NUM");
}
}
您还可以在github
中找到此代码