fn code_for_another_process() -> Result<(), Box<dyn std::error::Error>> {
let exe_name = "./rust_prog";
let code_name = "rust_prog.rs";
let mut file = std::fs::File::create(code_name)?;
use std::io::Write;
file.write_all(
"fn main() {\n\
println!(\"in another process\");\n\
}\n"
.as_bytes(),
)?;
drop(file); // ensure file is closed
let comp_status = std::process::Command::new("rustc")
.arg(code_name)
.status()?;
if comp_status.success() {
println!("~~~~ compilation of {} OK ~~~~", code_name);
let run_status = std::process::Command::new(exe_name).status()?;
if run_status.success() {
println!("~~~~ execution of {} OK ~~~~", exe_name);
}
}
Ok(())
}
fn code_for_this_process() -> Result<(), Box<dyn std::error::Error>> {
let lib_name = "./librust_lib.so";
let code_name = "rust_lib.rs";
let mut file = std::fs::File::create(code_name)?;
use std::io::Write;
file.write_all(
"#[no_mangle]\n\
pub extern \"C\" fn call_me(arg: i32) -> i32 {\n\
println!(\"called with {}\", arg);\n\
arg*2
}\n"
.as_bytes(),
)?;
drop(file); // ensure file is closed
let comp_status = std::process::Command::new("rustc")
.arg("--crate-type")
.arg("cdylib")
.arg(code_name)
.status()?;
if comp_status.success() {
println!("~~~~ compilation of {} OK ~~~~", code_name);
unsafe {
// requires dependency libloading = "0.7"
let lib = libloading::Library::new(lib_name)?;
let call_me: libloading::Symbol<
unsafe extern "C" fn(i32) -> i32,
> = lib.get(b"call_me")?;
for i in 0..5 {
println!("--> {}", call_me(i));
}
}
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
code_for_another_process()?;
code_for_this_process()?;
Ok(())
}
/*
~~~~ compilation of rust_prog.rs OK ~~~~
in another process
~~~~ execution of ./rust_prog OK ~~~~
~~~~ compilation of rust_lib.rs OK ~~~~
called with 0
--> 0
called with 1
--> 2
called with 2
--> 4
called with 3
--> 6
called with 4
--> 8
*/
If you really want something like this (I doubt) here are two very ugly solutions.
The first one generates some source code, compiles it in order to obtain an executable, then runs the executable in another process.
The second one generates some source code, compiles it in order to obtain a dynamic library, then loads this library (as a plugin) and accesses the symbol of the generated function in order to call it from the current process.
All of this supposes that you can use a Rust toolchain on the execution platform. The names are hardcoded and specific to my platform (UNIX); some logic may be needed in order to adapt to various platforms. A temporary directory could be used for the source code, the executable and the library in order to clean everything afterwards, but this is a detail.
fn code_for_another_process() -> Result<(), Box<dyn std::error::Error>> {
let exe_name = "./rust_prog";
let code_name = "rust_prog.rs";
let mut file = std::fs::File::create(code_name)?;
use std::io::Write;
file.write_all(
"fn main() {\n\
println!(\"in another process\");\n\
}\n"
.as_bytes(),
)?;
drop(file); // ensure file is closed
let comp_status = std::process::Command::new("rustc")
.arg(code_name)
.status()?;
if comp_status.success() {
println!("~~~~ compilation of {} OK ~~~~", code_name);
let run_status = std::process::Command::new(exe_name).status()?;
if run_status.success() {
println!("~~~~ execution of {} OK ~~~~", exe_name);
}
}
Ok(())
}
fn code_for_this_process() -> Result<(), Box<dyn std::error::Error>> {
let lib_name = "./librust_lib.so";
let code_name = "rust_lib.rs";
let mut file = std::fs::File::create(code_name)?;
use std::io::Write;
file.write_all(
"#[no_mangle]\n\
pub extern \"C\" fn call_me(arg: i32) -> i32 {\n\
println!(\"called with {}\", arg);\n\
arg*2
}\n"
.as_bytes(),
)?;
drop(file); // ensure file is closed
let comp_status = std::process::Command::new("rustc")
.arg("--crate-type")
.arg("cdylib")
.arg(code_name)
.status()?;
if comp_status.success() {
println!("~~~~ compilation of {} OK ~~~~", code_name);
unsafe {
// requires dependency libloading = "0.7"
let lib = libloading::Library::new(lib_name)?;
let call_me: libloading::Symbol<
unsafe extern "C" fn(i32) -> i32,
> = lib.get(b"call_me")?;
for i in 0..5 {
println!("--> {}", call_me(i));
}
}
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
code_for_another_process()?;
code_for_this_process()?;
Ok(())
}
/*
~~~~ compilation of rust_prog.rs OK ~~~~
in another process
~~~~ execution of ./rust_prog OK ~~~~
~~~~ compilation of rust_lib.rs OK ~~~~
called with 0
--> 0
called with 1
--> 2
called with 2
--> 4
called with 3
--> 6
called with 4
--> 8
*/
发布评论
评论(1)
如果您真的想要这样的东西(我怀疑),这里有两个非常丑陋的解决方案。
第一个生成一些源代码,对其进行编译以获取可执行文件,然后在另一个过程中运行可执行文件。
第二个生成一些源代码,对其进行编译以获取动态库,然后加载此库(作为插件)并访问生成的函数的符号,以便从当前过程中调用它。
所有这些都认为您可以在执行平台上使用Rust工具链。
名称是硬编码的,并且特定于我的平台(UNIX);为了适应各种平台,可能需要一些逻辑。
可以将临时目录用于源代码,可执行文件和库,以便以后清洁所有内容,但这是一个细节。
If you really want something like this (I doubt) here are two very ugly solutions.
The first one generates some source code, compiles it in order to obtain an executable, then runs the executable in another process.
The second one generates some source code, compiles it in order to obtain a dynamic library, then loads this library (as a plugin) and accesses the symbol of the generated function in order to call it from the current process.
All of this supposes that you can use a Rust toolchain on the execution platform.
The names are hardcoded and specific to my platform (UNIX); some logic may be needed in order to adapt to various platforms.
A temporary directory could be used for the source code, the executable and the library in order to clean everything afterwards, but this is a detail.