fusion-engineering / inline-python

Inline Python code directly in your Rust code
https://docs.rs/inline-python
BSD 2-Clause "Simplified" License
1.15k stars 37 forks source link

name is not defined in context #22

Closed hyousefGopher closed 4 years ago

hyousefGopher commented 4 years ago

I'm trying to call 2 different python blocks, where the first one run OpenCV camera and display output in frame, while the other block close this camera and destroy all windows, so I wrote the below code:

let c = inline_python::Context::new();

        match arg {
            "open" => {
                    python!  {
                            import cv2
                            #![context = &c]
                            cap = cv2.VideoCapture(0)
                            while cap.isOpened():
                                ret, frame = cap.read()
                                if ret:
                                    cv2.imshow("Frame", frame)
                                    if cv2.waitKey(25) & 0xFF == ord('q'):
                                       break
                                else:
                                    break        
                    }
            },
            "close" => {
                python!  {
                    #![context = &c]
                    cap.release()
                    cv2.destroyAllWindows()
                }
            },
            _ => (),
        }

But I got the below error while executing the block at close:

thread 'main' panicked at 'python!{...} failed to execute', src\main.rs:33:17 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace fatal runtime error: Rust panics must be rethrown

My full code is:

#![feature(proc_macro_hygiene)]
use inline_python::{Context, python};

use web_view::*;

fn main() {
    let c = inline_python::Context::new();
    web_view::builder()
    .title("Call open CV")
    .content(Content::Html(HTML))
    .size(800, 600)
    .user_data(())
    .invoke_handler(|_, arg| {
        match arg {
            "open" => {
                    python!  {
                            import cv2
                            #![context = &c]
                            cap = cv2.VideoCapture(0)
                            while cap.isOpened():
                                ret, frame = cap.read()
                                if ret:
                                    cv2.imshow("Frame", frame)
                                    if cv2.waitKey(25) & 0xFF == ord('q'):
                                       break
                                else:
                                    break    
                           cap.release()
                          cv2.destroyAllWindows()    
                    }
            },
            "close" => {
                python!  {
                    #![context = &c]
                    cap.release()
                    cv2.destroyAllWindows()
                }
            },
            _ => (),
        }
        Ok(())
    }).run()
    .unwrap();
}

const HTML: &str  = r#"
<!doctype html>
<html>
    <body>
        <button onclick="external.invoke('open')">Run</button>
        <button onclick="external.invoke('close')">Close</button>
    </body>
</html>
"#;
de-vri-es commented 4 years ago

This is a problem:

python!  {
  import cv2
  #![context = &c]
  ...
}

The context attribute needs to be the very first line, just as with attributes for Rust modules. Otherwise it is passed to python, which treats it as a comment.

Note though that the context attribute is no longer supported in version 0.5.0, which will be released sometime soon. Instead, you will have to write this:

context.run(python! {
  ...
});

But for now, just swap the import and the context attribute in your code.

de-vri-es commented 4 years ago

Note that 0.5.0 was just released, so if you update you can swap to context.run() :)

hyousefGopher commented 4 years ago

Thanks, worked also with the 0.5.0 perfectly, as below:

#![feature(proc_macro_hygiene)]
use inline_python::*;

use web_view::*;

fn main() {
    let c = Context::new();
    web_view::builder()
    .title("Call open CV")
    .content(Content::Html(HTML))
    .size(800, 600)
    .user_data(())
    .invoke_handler(|_, arg| {
        match arg {
            "open" => {
                c.run(python!  {
                            import cv2
                            cap = cv2.VideoCapture(0)
                            while cap.isOpened():
                                ret, frame = cap.read()
                                if ret:
                                    cv2.imshow("Frame", frame)
                                    if cv2.waitKey(25) & 0xFF == ord('q'):
                                       break
                                else:
                                    break 
                            cap.release()
                            cv2.destroyAllWindows()       
                    })
            },
            "close" => {
                c.run(python!  {
                    cap.release()
                    cv2.destroyAllWindows()
                })
            },
            _ => (),
        }
        Ok(())
    }).run()
    .unwrap();
}

const HTML: &str  = r#"
<!doctype html>
<html>
    <body>
        <button onclick="external.invoke('open')">Run</button>
        <button onclick="external.invoke('close')">Close</button><br>
        <br>

    </body>
</html>
"#;
de-vri-es commented 4 years ago

Nice, thanks for lettings us know :)