Skip to main content

basic_debug/
basic_debug.rs

1//! Minimal example: set a breakpoint, run Lua code, inspect locals.
2//!
3//! ```sh
4//! cargo run --example basic_debug
5//! ```
6
7use mlua::prelude::*;
8use mlua_probe_core::{DebugEvent, DebugSession};
9
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    let lua = Lua::new();
12
13    // Create debug session + controller.
14    let (session, controller) = DebugSession::new();
15    session.attach(&lua)?;
16
17    // Set a breakpoint on line 4.
18    let bp_id = controller.set_breakpoint("@example.lua", 4, None)?;
19    println!("Breakpoint {bp_id} set at @example.lua:4");
20
21    // Run Lua code on a separate thread.
22    // mlua 0.11's LuaError is not Send, so convert to a string error
23    // for cross-thread transport.
24    let handle = std::thread::spawn(move || -> Result<i64, String> {
25        lua.load(
26            r#"
27local a = 10
28local b = 20
29local c = 30
30local result = a + b + c
31return result
32"#,
33        )
34        .set_name("@example.lua")
35        .eval::<i64>()
36        .map_err(|e| e.to_string())
37    });
38
39    // Wait for the breakpoint hit.
40    match controller.wait_event()? {
41        DebugEvent::Paused { reason, stack } => {
42            println!("VM paused: {reason:?}");
43            for frame in &stack {
44                let line_str = frame
45                    .line
46                    .map_or_else(|| "?".to_string(), |l| l.to_string());
47                println!(
48                    "  frame {}: {} ({}:{})",
49                    frame.id, frame.name, frame.source, line_str
50                );
51            }
52
53            // Inspect locals.
54            match controller.get_locals(0) {
55                Ok(locals) => {
56                    println!("Locals:");
57                    for var in &locals {
58                        println!("  {} = {} ({})", var.name, var.value, var.type_name);
59                    }
60                }
61                Err(e) => println!("Failed to get locals: {e}"),
62            }
63
64            // Evaluate an expression.
65            match controller.evaluate("a + b", None) {
66                Ok(result) => println!("Eval 'a + b' = {result}"),
67                Err(e) => println!("Eval failed: {e}"),
68            }
69        }
70        other => println!("Unexpected event: {other:?}"),
71    }
72
73    // Resume.
74    controller.continue_execution()?;
75
76    // Wait for completion.
77    let result = handle.join().unwrap()?;
78    println!("Lua returned: {result}");
79
80    Ok(())
81}