diff options
| author | Matthew Collins <[email protected]> | 2018-05-05 15:46:12 +0100 |
|---|---|---|
| committer | Matthew Collins <[email protected]> | 2018-05-05 15:46:12 +0100 |
| commit | 5ef3f6e17cd14d452cfcdbb8a30abf61e513e84d (patch) | |
| tree | e667ed1dccc3d3ac0df83e8c66b76dd5dc0771e8 /src/callback.rs | |
| parent | Minor bump due to slight mistake with last publish (diff) | |
| download | steamworks-rs-5ef3f6e17cd14d452cfcdbb8a30abf61e513e84d.tar.xz steamworks-rs-5ef3f6e17cd14d452cfcdbb8a30abf61e513e84d.zip | |
Rework how the sys crate is generated
Due to packing issues with steam's structs we use wrapper methods
to access the fields and create the structs.
Diffstat (limited to 'src/callback.rs')
| -rw-r--r-- | src/callback.rs | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/src/callback.rs b/src/callback.rs index d249207..6808a45 100644 --- a/src/callback.rs +++ b/src/callback.rs @@ -5,6 +5,9 @@ use sys; use std::mem; use std::sync::{ Arc, Weak }; +use std::panic::*; +use std::any::Any; +use std::process::abort; pub unsafe trait Callback { const ID: i32; @@ -12,6 +15,16 @@ pub unsafe trait Callback { unsafe fn from_raw(raw: *mut c_void) -> Self; } +fn print_err(err: Box<Any>) { + if let Some(err) = err.downcast_ref::<&str>() { + println!("Steam callback paniced: {}", err); + } else if let Some(err) = err.downcast_ref::<String>() { + println!("Steam callback paniced: {}", err); + } else { + println!("Steam callback paniced"); + } +} + pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager>>, f: F, game_server: bool) where C: Callback, F: FnMut(C) + Send + Sync + 'static @@ -25,7 +38,7 @@ pub(crate) unsafe fn register_callback<C, F, Manager>(inner: &Arc<Inner<Manager> func(param); } - unsafe extern "C" fn run_extra<C, F>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, _: bool, _: sys::SteamAPICall) + unsafe extern "C" fn run_extra<C, F>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, _: u8, _: sys::SteamAPICall) where C: Callback, F: FnMut(C) + Send + Sync + 'static { @@ -72,18 +85,46 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag where F: for<'a> FnMut(&'a C, bool) + Send + Sync + 'static { let data: &mut CallData<F, Manager> = &mut *(userdata as *mut CallData<F, Manager>); - (data.func)(&*(param as *const _), false); - + #[cfg(debug_assertions)] + { + let res = catch_unwind(AssertUnwindSafe(|| + (data.func)(&*(param as *const _), false) + )); + if let Err(err) = res { + print_err(err); + abort(); + } + + } + #[cfg(not(debug_assertions))] + { + (data.func)(&*(param as *const _), false); + } + sys::delete_rust_callback(cb); } - unsafe extern "C" fn run_extra<C, F, Manager>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, io_error: bool, api_call: sys::SteamAPICall) + unsafe extern "C" fn run_extra<C, F, Manager>(cb: *mut c_void, userdata: *mut c_void, param: *mut c_void, io_error: u8, api_call: sys::SteamAPICall) where F: for<'a> FnMut(&'a C, bool) + Send + Sync + 'static { let data: &mut CallData<F, Manager> = &mut *(userdata as *mut CallData<F, Manager>); if api_call == data.api_call { - (data.func)(&*(param as *const _), io_error); + #[cfg(debug_assertions)] + { + let res = catch_unwind(AssertUnwindSafe(|| + (data.func)(&*(param as *const _), io_error != 0) + )); + if let Err(err) = res { + print_err(err); + abort(); + } + + } + #[cfg(not(debug_assertions))] + { + (data.func)(&*(param as *const _), io_error != 0); + } sys::delete_rust_callback(cb); } } @@ -94,8 +135,6 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag let data: Box<CallData<F, Manager>> = Box::from_raw(userdata as _); if let Some(inner) = data.inner.upgrade() { - sys::SteamAPI_UnregisterCallResult(cb, data.api_call); - let mut cbs = inner.callbacks.lock().unwrap(); cbs.call_results.remove(&data.api_call); } @@ -110,7 +149,7 @@ pub(crate) unsafe fn register_call_result<C, F, Manager>(inner: &Arc<Inner<Manag }; let data = sys::CallbackData { - param_size: mem::size_of::<C> as _, + param_size: mem::size_of::<C>() as _, userdata: Box::into_raw(Box::new(userdata)) as _, run: run::<C, F, Manager>, run_extra: run_extra::<C, F, Manager>, |