From 04ea6ebc3f0f0f5277b402fab1557da617e273ea Mon Sep 17 00:00:00 2001 From: HampusM Date: Sun, 8 Sep 2024 00:01:49 +0200 Subject: refactor(glfw): use C-unwind ABI --- glfw/build.rs | 18 ++++++- glfw/src/window.rs | 141 ++++++++++++++++++----------------------------------- 2 files changed, 63 insertions(+), 96 deletions(-) diff --git a/glfw/build.rs b/glfw/build.rs index aaf4446..18ac677 100644 --- a/glfw/build.rs +++ b/glfw/build.rs @@ -1,8 +1,10 @@ use std::env; use std::error::Error; +use std::fs::OpenOptions; +use std::io::Write; use std::path::PathBuf; -use bindgen::MacroTypeVariation; +use bindgen::{Abi, MacroTypeVariation}; fn main() -> Result<(), Box> { @@ -17,12 +19,24 @@ fn main() -> Result<(), Box> .allowlist_function("glfw.*") .allowlist_type("GLFW.*") .allowlist_var("GLFW.*") + .blocklist_type("GLFWglproc") .default_macro_constant_type(MacroTypeVariation::Signed) + .override_abi(Abi::CUnwind, ".*") .generate()?; let out_path = PathBuf::from(env::var("OUT_DIR")?); - bindings.write_to_file(out_path.join("bindings.rs"))?; + let bindings_file_path = out_path.join("bindings.rs"); + + bindings.write_to_file(&bindings_file_path)?; + + let mut bindings_file = OpenOptions::new().append(true).open(bindings_file_path)?; + + // Cannot be C-unwind :( + writeln!( + bindings_file, + "pub type GLFWglproc = ::std::option::Option;" + )?; Ok(()) } diff --git a/glfw/src/window.rs b/glfw/src/window.rs index 9a15796..53a8420 100644 --- a/glfw/src/window.rs +++ b/glfw/src/window.rs @@ -2,7 +2,6 @@ use std::cell::RefCell; use std::ffi::{c_double, c_int, CString}; use std::hint::unreachable_unchecked; use std::io::{stdout, Write}; -use std::panic::catch_unwind; use std::ptr::null_mut; use bitflags::bitflags; @@ -734,25 +733,18 @@ static MOUSE_BUTTON_CALLBACK: RefCell> = RefCell::ne static FOCUS_CALLBACK: RefCell> = RefCell::new(None); } -extern "C" fn close_callback(_window: *mut crate::ffi::GLFWwindow) +extern "C-unwind" fn close_callback(_window: *mut crate::ffi::GLFWwindow) { - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - CLOSE_CALLBACK - .try_with(|close_cb| { - if let Some(cb) = close_cb.borrow().as_deref() { - cb(); - } - }) - .ok(); - }); - - if res.is_err() { - println!("ERROR: Panic in window close callback"); - } + CLOSE_CALLBACK + .try_with(|close_cb| { + if let Some(cb) = close_cb.borrow().as_deref() { + cb(); + } + }) + .ok(); } -extern "C" fn framebuffer_size_callback( +extern "C-unwind" fn framebuffer_size_callback( _window: *mut crate::ffi::GLFWwindow, c_width: c_int, c_height: c_int, @@ -762,23 +754,16 @@ extern "C" fn framebuffer_size_callback( let width = u32::from_le_bytes(c_width.to_le_bytes()); let height = u32::from_le_bytes(c_height.to_le_bytes()); - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - FRAMEBUFFER_SIZE_CB - .try_with(|framebuffer_size_cb| { - if let Some(cb) = framebuffer_size_cb.borrow().as_deref() { - cb(Size { width, height }); - } - }) - .ok(); - }); - - if res.is_err() { - println!("ERROR: Panic in framebuffer size callback"); - } + FRAMEBUFFER_SIZE_CB + .try_with(|framebuffer_size_cb| { + if let Some(cb) = framebuffer_size_cb.borrow().as_deref() { + cb(Size { width, height }); + } + }) + .ok(); } -extern "C" fn key_callback( +extern "C-unwind" fn key_callback( _window: *mut crate::ffi::GLFWwindow, key_raw: c_int, scancode: c_int, @@ -806,49 +791,31 @@ extern "C" fn key_callback( return; }; - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - KEY_CALLBACK - .try_with(|key_callback| { - if let Some(cb) = key_callback.borrow().as_deref() { - cb(key, scancode, key_state, key_modifiers); - } - }) - .ok(); - }); - - if res.is_err() { - write!(stdout(), "ERROR: Panic in key callback").ok(); - } + KEY_CALLBACK + .try_with(|key_callback| { + if let Some(cb) = key_callback.borrow().as_deref() { + cb(key, scancode, key_state, key_modifiers); + } + }) + .ok(); } -extern "C" fn cursor_pos_callback( +extern "C-unwind" fn cursor_pos_callback( _window: *mut crate::ffi::GLFWwindow, x_pos: c_double, y_pos: c_double, ) { - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - CURSOR_POS_CALLBACK - .try_with(|cursor_pos_callback| { - if let Some(cb) = cursor_pos_callback.borrow().as_deref() { - cb(CursorPosition { x: x_pos, y: y_pos }); - } - }) - .ok(); - }); - - if res.is_err() { - write!( - stdout(), - "ERROR: Cursor position callback panicked: {res:?}" - ) + CURSOR_POS_CALLBACK + .try_with(|cursor_pos_callback| { + if let Some(cb) = cursor_pos_callback.borrow().as_deref() { + cb(CursorPosition { x: x_pos, y: y_pos }); + } + }) .ok(); - } } -extern "C" fn mouse_button_callback( +extern "C-unwind" fn mouse_button_callback( _window: *mut crate::ffi::GLFWwindow, mouse_button_raw: c_int, mouse_action: c_int, @@ -875,23 +842,16 @@ extern "C" fn mouse_button_callback( return; }; - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - MOUSE_BUTTON_CALLBACK - .try_with(|mouse_button_callback| { - if let Some(cb) = mouse_button_callback.borrow().as_deref() { - cb(mouse_button, mouse_button_state, key_modifiers); - } - }) - .ok(); - }); - - if res.is_err() { - write!(stdout(), "ERROR: Mouse button callback panicked: {res:?}").ok(); - } + MOUSE_BUTTON_CALLBACK + .try_with(|mouse_button_callback| { + if let Some(cb) = mouse_button_callback.borrow().as_deref() { + cb(mouse_button, mouse_button_state, key_modifiers); + } + }) + .ok(); } -extern "C" fn focus_callback(_window: *mut crate::ffi::GLFWwindow, focused: c_int) +extern "C-unwind" fn focus_callback(_window: *mut crate::ffi::GLFWwindow, focused: c_int) { let is_focused = if focused == crate::ffi::GLFW_TRUE { true @@ -902,18 +862,11 @@ extern "C" fn focus_callback(_window: *mut crate::ffi::GLFWwindow, focused: c_in return; }; - // Unwinds are catched because unwinding from Rust code into foreign code is UB. - let res = catch_unwind(|| { - FOCUS_CALLBACK - .try_with(|focus_callback| { - if let Some(cb) = focus_callback.borrow().as_deref() { - cb(is_focused); - } - }) - .ok(); - }); - - if res.is_err() { - write!(stdout(), "ERROR: Focus callback panicked: {res:?}").ok(); - } + FOCUS_CALLBACK + .try_with(|focus_callback| { + if let Some(cb) = focus_callback.borrow().as_deref() { + cb(is_focused); + } + }) + .ok(); } -- cgit v1.2.3-18-g5258