aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Parrill <[email protected]>2019-06-05 22:26:21 -0400
committerMatthew Collins <[email protected]>2019-06-09 23:50:11 +0100
commit99051706e18f66f2e63494242dda41e7a7256971 (patch)
tree13024d70399eb3fa57b106cec85d85874a8f629a
parent0.5.1 (and 0.5.0 for sys) (diff)
downloadsteamworks-rs-99051706e18f66f2e63494242dda41e7a7256971.tar.xz
steamworks-rs-99051706e18f66f2e63494242dda41e7a7256971.zip
Add Utils::set_warning_callback for logging Steam warnings
-rw-r--r--Cargo.toml1
-rw-r--r--src/lib.rs2
-rw-r--r--src/utils.rs54
-rw-r--r--steamworks-sys/src/lib.rs1
4 files changed, 57 insertions, 1 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 8a47a54..cc588be 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,3 +28,4 @@ steamworks-sys = {path = "./steamworks-sys", version = "0.5.0"}
failure = "0.1.5"
bitflags = "1.0.4"
libc = "0.2.50"
+lazy_static = "1.3.0"
diff --git a/src/lib.rs b/src/lib.rs
index ce40d56..1bcf828 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,6 +5,8 @@ extern crate steamworks_sys as sys;
extern crate failure;
#[macro_use]
extern crate bitflags;
+#[macro_use]
+extern crate lazy_static;
mod error;
pub use crate::error::*;
diff --git a/src/utils.rs b/src/utils.rs
index 34ba6c9..3d569b3 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -1,6 +1,12 @@
use super::*;
+use libc::c_char;
+use std::ffi::CStr;
+use std::panic;
+use std::process::abort;
+use std::sync::RwLock;
+
/// Access to the steam utils interface
pub struct Utils<Manager> {
pub(crate) utils: *mut sys::ISteamUtils,
@@ -14,6 +20,36 @@ pub enum NotificationPosition {
BottomRight,
}
+lazy_static!{
+ /// Global rust warning callback
+ static ref WARNING_CALLBACK: RwLock<Option<Box<Fn(i32, &CStr) + Send + Sync>>> = RwLock::new(None);
+}
+
+/// C function to pass as the real callback, which forwards to the `WARNING_CALLBACK` if any
+unsafe extern "cdecl" fn c_warning_callback(level: i32, msg: *const c_char) {
+ let lock = WARNING_CALLBACK.read().expect("warning func lock poisoned");
+ let cb = match lock.as_ref() {
+ Some(cb) => cb,
+ None => { return; }
+ };
+
+ let s = CStr::from_ptr(msg);
+
+ let res = panic::catch_unwind(panic::AssertUnwindSafe(||
+ cb(level, s)
+ ));
+ if let Err(err) = res {
+ if let Some(err) = err.downcast_ref::<&str>() {
+ println!("Steam warning callback paniced: {}", err);
+ } else if let Some(err) = err.downcast_ref::<String>() {
+ println!("Steam warning callback paniced: {}", err);
+ } else {
+ println!("Steam warning callback paniced");
+ }
+ abort();
+ }
+}
+
impl <Manager> Utils<Manager> {
/// Returns the app ID of the current process
pub fn app_id(&self) -> AppId {
@@ -47,4 +83,20 @@ impl <Manager> Utils<Manager> {
sys::SteamAPI_ISteamUtils_SetOverlayNotificationPosition(self.utils, position);
}
}
-} \ No newline at end of file
+
+ /// Sets the Steam warning callback, which is called to emit warning messages.
+ ///
+ /// The passed-in function takes two arguments: a severity level (0 = info, 1 = warning) and
+ /// the message itself.
+ ///
+ /// See [Steamwork's debugging page](https://partner.steamgames.com/doc/sdk/api/debugging) for more info.
+ pub fn set_warning_callback<F>(&self, cb: F)
+ where F: Fn(i32, &CStr) + Send + Sync + 'static
+ {
+ let mut lock = WARNING_CALLBACK.write().expect("warning func lock poisoned");
+ *lock = Some(Box::new(cb));
+ unsafe {
+ sys::SteamAPI_ISteamUtils_SetWarningMessageHook(self.utils, c_warning_callback);
+ }
+ }
+}
diff --git a/steamworks-sys/src/lib.rs b/steamworks-sys/src/lib.rs
index bcbd33d..f32b784 100644
--- a/steamworks-sys/src/lib.rs
+++ b/steamworks-sys/src/lib.rs
@@ -100,6 +100,7 @@ extern "C" {
pub fn SteamAPI_ISteamUtils_SetOverlayNotificationPosition(instance: *mut ISteamUtils, position: ENotificationPosition);
pub fn SteamAPI_ISteamUtils_GetImageSize(instance: *mut ISteamUtils, image: c_int, width: *mut u32, height: *mut u32) -> u8;
pub fn SteamAPI_ISteamUtils_GetImageRGBA(instance: *mut ISteamUtils, image: c_int, dest: *mut u8, dest_size: c_int) -> u8;
+ pub fn SteamAPI_ISteamUtils_SetWarningMessageHook(instance: *mut ISteamUtils, func: unsafe extern "cdecl" fn(i32, *const c_char));
pub fn SteamAPI_ISteamApps_BIsAppInstalled(instance: *mut ISteamApps, app_id: AppId_t) -> u8;
pub fn SteamAPI_ISteamApps_BIsDlcInstalled(instance: *mut ISteamApps, app_id: AppId_t) -> u8;