|
| 1 | +use rustpython::vm::*; |
| 2 | +use rustpython_vm as vm; |
| 3 | +use rustpython_vm::builtins::PyModule; |
| 4 | + |
| 5 | +/// A global fn called from Python which extracts the id from the injected module and returns / prints it to the console. |
| 6 | +/// This is useful in a multi-threaded environment where you may have several threads sharing global functions. The |
| 7 | +/// id would allow a local context for each thread, for example by using a global Arc<Mutex<Hashmap>>. |
| 8 | +fn get_id(vm: &vm::VirtualMachine) -> PyResult<i32> { |
| 9 | + let module = vm.import("__id_module", 0)?; |
| 10 | + let obj = module.get_attr("__id", vm)?; |
| 11 | + let id = obj.try_to_value::<i32>(vm)?; |
| 12 | + |
| 13 | + println!("The id is {}", id); |
| 14 | + |
| 15 | + Ok(id) |
| 16 | +} |
| 17 | + |
| 18 | +fn main() -> vm::PyResult<()> { |
| 19 | + vm::Interpreter::without_stdlib(Default::default()).enter(|vm| { |
| 20 | + let scope = vm.new_scope_with_builtins(); |
| 21 | + |
| 22 | + // Register the global function |
| 23 | + let _ = scope |
| 24 | + .globals |
| 25 | + .set_item("get_id", vm.new_function("get_id", get_id).into(), vm); |
| 26 | + |
| 27 | + // Create a module and set an id |
| 28 | + let module = PyModule::new().into_ref(&vm.ctx); |
| 29 | + module |
| 30 | + .as_object() |
| 31 | + .set_attr("__id", vm.new_pyobj(42_i32), vm)?; |
| 32 | + |
| 33 | + // Register the module |
| 34 | + let sys = vm.import("sys", 0)?; |
| 35 | + let modules = sys.get_attr("modules", vm)?; |
| 36 | + modules.set_item("__id_module", module.into(), vm)?; |
| 37 | + |
| 38 | + // Execute the code |
| 39 | + let source = r#"get_id()"#; |
| 40 | + let code_obj = vm |
| 41 | + .compile(source, vm::compiler::Mode::Exec, "<embedded>".to_owned()) |
| 42 | + .map_err(|err| vm.new_syntax_error(&err, Some(source)))?; |
| 43 | + |
| 44 | + vm.run_code_obj(code_obj, scope)?; |
| 45 | + |
| 46 | + Ok(()) |
| 47 | + }) |
| 48 | +} |
0 commit comments