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
*/