Skip to content

Commit

Permalink
Add unwind support (closes #2)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zerthox committed Aug 15, 2023
1 parent 76c70f0 commit 75d5f3d
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 136 deletions.
9 changes: 5 additions & 4 deletions arcdps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "arcdps"
version = "0.12.0"
version = "0.13.0"
authors = ["Zerthox", "Greaka"]
edition = "2021"
description = "Rust bindings for ArcDPS plugins"
Expand All @@ -15,12 +15,12 @@ arcdps_evtc = { path = "../arcdps_evtc" }
arcdps-imgui = { version = "0.8.0", features = ["tables-api"] }
chrono = { version = "0.4.24", optional = true }
log = { version = "0.4.17", features = ["std"], optional = true }
num_enum = "0.6.0"
num_enum = "0.7.0"
serde = { version = "1.0.160", features = ["derive"], optional = true }
strum = { version = "0.25.0", features = ["derive"], optional = true }

[dependencies.windows]
version = "0.48.0"
version = "0.51.0"
features = [
"System",
"Win32_Foundation",
Expand All @@ -31,7 +31,8 @@ features = [
]

[features]
default = []
default = ["unwind"]
unwind = ["arcdps_codegen/unwind"]
extras = ["arcdps_codegen/extras", "chrono"]
serde = ["dep:serde", "arcdps_evtc/serde", "chrono/serde"]
strum = ["dep:strum", "arcdps_evtc/strum"]
39 changes: 21 additions & 18 deletions arcdps/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{
evtc::{Agent, CombatEvent, RawAgent, RawCombatEvent},
imgui,
util::abi,
};
use std::os::raw::c_char;
use windows::Win32::Foundation::{HWND, LPARAM, WPARAM};
Expand Down Expand Up @@ -74,20 +75,8 @@ pub type ReleaseFunc = fn();

pub type UpdateUrlFunc = fn() -> Option<String>;

pub type RawWndProcCallback =
unsafe extern "C" fn(h_wnd: HWND, u_msg: u32, w_param: WPARAM, l_param: LPARAM) -> u32;

pub type WndProcCallback = fn(key: usize, key_down: bool, prev_key_down: bool) -> bool;

pub type RawCombatCallback = unsafe extern "C" fn(
event: *const RawCombatEvent,
src: *const RawAgent,
dst: *const RawAgent,
skill_name: *const c_char,
id: u64,
revision: u64,
);

pub type CombatCallback = fn(
event: Option<CombatEvent>,
src: Option<Agent>,
Expand All @@ -97,14 +86,28 @@ pub type CombatCallback = fn(
revision: u64,
);

pub type RawImguiCallback = unsafe extern "C" fn(not_character_select_or_loading: u32);

pub type ImguiCallback = fn(ui: &imgui::Ui, not_character_select_or_loading: bool);

pub type RawOptionsCallback = unsafe extern "C" fn();

pub type OptionsCallback = fn(ui: &imgui::Ui);

pub type RawOptionsWindowsCallback = unsafe extern "C" fn(window_name: *const c_char) -> bool;

pub type OptionsWindowsCallback = fn(ui: &imgui::Ui, window_name: Option<&str>) -> bool;

abi! {
pub type RawWndProcCallback =
unsafe extern fn(h_wnd: HWND, u_msg: u32, w_param: WPARAM, l_param: LPARAM) -> u32;

pub type RawCombatCallback = unsafe extern fn(
event: *const RawCombatEvent,
src: *const RawAgent,
dst: *const RawAgent,
skill_name: *const c_char,
id: u64,
revision: u64,
);

pub type RawImguiCallback = unsafe extern fn(not_character_select_or_loading: u32);

pub type RawOptionsCallback = unsafe extern fn();

pub type RawOptionsWindowsCallback = unsafe extern fn(window_name: *const c_char) -> bool;
}
34 changes: 18 additions & 16 deletions arcdps/src/extras/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,31 @@ use super::{
user::{RawUserInfo, UserInfoIter},
ExtrasAddonInfo, ExtrasSubscriberInfo, RawExtrasAddonInfo,
};
use crate::evtc::Language;

pub type RawExtrasSubscriberInit = unsafe extern "C" fn(
extras_info: *const RawExtrasAddonInfo,
subscriber_info: *mut ExtrasSubscriberInfo,
);
use crate::{evtc::Language, util::abi};

pub type ExtrasInitFunc = fn(extras_info: ExtrasAddonInfo, account_name: Option<&str>);

pub type RawExtrasSquadUpdateCallback =
unsafe extern "C" fn(updated_users: *const RawUserInfo, updated_users_count: u64);

pub type ExtrasSquadUpdateCallback = fn(updated_users: UserInfoIter);

pub type RawExtrasLanguageChangedCallback = unsafe extern "C" fn(new_language: Language);

pub type ExtrasLanguageChangedCallback = fn(new_language: Language);

pub type RawExtrasKeybindChangedCallback = unsafe extern "C" fn(changed: RawKeybindChange);

pub type ExtrasKeybindChangedCallback = fn(changed: KeybindChange);

pub type RawExtrasChatMessageCallback =
unsafe extern "C" fn(chat_message: *const RawChatMessageInfo);

pub type ExtrasChatMessageCallback = fn(chat_message_info: &ChatMessageInfo);

abi! {
pub type RawExtrasSubscriberInit = unsafe extern fn(
extras_info: *const RawExtrasAddonInfo,
subscriber_info: *mut ExtrasSubscriberInfo,
);

pub type RawExtrasSquadUpdateCallback =
unsafe extern fn(updated_users: *const RawUserInfo, updated_users_count: u64);

pub type RawExtrasLanguageChangedCallback = unsafe extern fn(new_language: Language);

pub type RawExtrasKeybindChangedCallback = unsafe extern fn(changed: RawKeybindChange);

pub type RawExtrasChatMessageCallback =
unsafe extern fn(chat_message: *const RawChatMessageInfo);
}
26 changes: 9 additions & 17 deletions arcdps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,30 +274,22 @@ pub struct SupportedFields {
/// Exports for usage in macros.
#[doc(hidden)]
pub mod __macro {
pub mod prelude {
pub use crate::{
callbacks::*,
globals::{FreeFn, MallocFn},
};
pub use std::os::raw::{c_char, c_void};
pub use windows::Win32::{
Foundation::{HMODULE, HWND, LPARAM, WPARAM},
UI::WindowsAndMessaging::{WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP},
};

#[cfg(feature = "extras")]
pub use crate::extras::callbacks::*;
}

pub use crate::util::{str_from_cstr, str_to_wide, strip_account_prefix};
pub use crate::{
globals::{FreeFn, MallocFn},
util::{str_from_cstr, str_to_wide, strip_account_prefix},
};
pub use std::os::raw::{c_char, c_void};
pub use windows::Win32::{
Foundation::{HMODULE, HWND, LPARAM, WPARAM},
UI::WindowsAndMessaging::{WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP},
};

use crate::{
exports::{has_e3_log_file, has_e8_log_window},
globals::{init_dxgi, init_imgui, ARC_GLOBALS, IG_UI},
imgui,
panic::init_panic_hook,
};
use prelude::*;

#[cfg(feature = "log")]
use crate::log::ArcDpsLogger;
Expand Down
15 changes: 15 additions & 0 deletions arcdps/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,18 @@ pub unsafe fn str_to_wide(string: impl AsRef<str>) -> Vec<u16> {
.chain(iter::once(0))
.collect()
}

/// Helper to define function types with optional unwind ABI.
macro_rules! abi {
( $( $vis:vis type $name:ident = unsafe extern fn( $( $args:tt )* ) $( -> $ret:ty )? ; )* ) => {
$(
#[cfg(feature = "unwind")]
$vis type $name = unsafe extern "C-unwind" fn( $( $args )* ) $( -> $ret )?;

#[cfg(not(feature = "unwind"))]
$vis type $name = unsafe extern "C" fn( $( $args )* ) $( -> $ret )?;
)*
};
}

pub(crate) use abi;
3 changes: 2 additions & 1 deletion arcdps_codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "arcdps_codegen"
version = "0.10.0"
version = "0.10.1"
authors = ["Zerthox", "Greaka"]
edition = "2021"
description = "Helper macro to generate code for ArcDPS plugins"
Expand All @@ -17,4 +17,5 @@ quote = "1.0.26"
syn = { version = "2.0.14", features = ["full"] }

[features]
unwind = []
extras = []
21 changes: 21 additions & 0 deletions arcdps_codegen/src/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use cfg_if::cfg_if;

pub const C_ABI: &str = {
cfg_if! {
if #[cfg(feature = "unwind")] {
"C-unwind"
} else {
"C"
}
}
};

pub const SYSTEM_ABI: &str = {
cfg_if! {
if #[cfg(feature = "unwind")] {
"system-unwind"
} else {
"system"
}
}
};
66 changes: 36 additions & 30 deletions arcdps_codegen/src/callbacks.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{ArcDpsGen, CallbackInfo};
use crate::{
abi::{C_ABI, SYSTEM_ABI},
ArcDpsGen, CallbackInfo,
};
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned};
use syn::Expr;
Expand All @@ -10,12 +13,12 @@ impl ArcDpsGen {
let span = syn::Error::new_spanned(init, "").span();
quote_spanned! {span=>
{
const SAFE: InitFunc = #init;
const SAFE: ::arcdps::callbacks::InitFunc = #init;
SAFE()
}
}
} else {
quote! { Ok(()) }
quote! { ::std::result::Result::Ok(()) }
}
}

Expand All @@ -25,7 +28,7 @@ impl ArcDpsGen {
let span = syn::Error::new_spanned(release, "").span();
quote_spanned! {span=>
{
const SAFE: ReleaseFunc = #release;
const SAFE: ::arcdps::callbacks::ReleaseFunc = #release;
SAFE()
}
}
Expand All @@ -39,13 +42,13 @@ impl ArcDpsGen {
if let Some(update_url) = &self.update_url {
let span = syn::Error::new_spanned(update_url, "").span();
quote_spanned! {span=>
static mut UPDATE_URL: Vec<u16> = Vec::new();
static mut UPDATE_URL: ::std::vec::Vec<u16> = ::std::vec::Vec::new();

#[no_mangle]
pub unsafe extern "system" fn get_update_url() -> *const u16 {
const SAFE: UpdateUrlFunc = #update_url;
pub unsafe extern #SYSTEM_ABI fn get_update_url() -> *const ::std::primitive::u16 {
const SAFE: ::arcdps::callbacks::UpdateUrlFunc = #update_url;

if let Some(url) = SAFE() {
if let ::std::option::Option::Some(url) = SAFE() {
UPDATE_URL = ::arcdps::__macro::str_to_wide(url);
UPDATE_URL.as_ptr()
} else {
Expand Down Expand Up @@ -83,16 +86,19 @@ impl ArcDpsGen {
/// Helper to generate a wnd callback wrapper.
fn wnd_wrapper(name: TokenStream, safe: &Expr, span: Span) -> TokenStream {
quote_spanned! {span=>
unsafe extern "C" fn #name(
_h_wnd: HWND,
u_msg: u32,
w_param: WPARAM,
l_param: LPARAM,
) -> u32 {
const SAFE: WndProcCallback = #safe;
unsafe extern #C_ABI fn #name(
_h_wnd: ::arcdps::__macro::HWND,
u_msg: ::std::primitive::u32,
w_param: ::arcdps::__macro::WPARAM,
l_param: ::arcdps::__macro::LPARAM,
) -> ::std::primitive::u32 {
const SAFE: ::arcdps::callbacks::WndProcCallback = #safe;

match u_msg {
WM_KEYDOWN | WM_KEYUP | WM_SYSKEYDOWN | WM_SYSKEYUP => {
::arcdps::__macro::WM_KEYDOWN
| ::arcdps::__macro::WM_KEYUP
| ::arcdps::__macro::WM_SYSKEYDOWN
| ::arcdps::__macro::WM_SYSKEYUP => {
let key_down = u_msg & 1 == 0;
let prev_key_down = (l_param.0 >> 30) & 1 == 1;

Expand All @@ -116,8 +122,8 @@ impl ArcDpsGen {
quote! { abstract_options_windows },
|safe, span| {
quote_spanned! {span=>
unsafe extern "C" fn abstract_options_windows(window_name: *const c_char) -> bool {
const SAFE: OptionsWindowsCallback = #safe;
unsafe extern #C_ABI fn abstract_options_windows(window_name: *const c_char) -> ::std::bool {
const SAFE: ::arcdps::callbacks::OptionsWindowsCallback = #safe;

SAFE(::arcdps::__macro::ui(), ::arcdps::__macro::str_from_cstr(window_name))
}
Expand All @@ -134,8 +140,8 @@ impl ArcDpsGen {
quote! { abstract_options_end },
|safe, span| {
quote_spanned! {span=>
unsafe extern "C" fn abstract_options_end() {
const SAFE: OptionsCallback = #safe;
unsafe extern #C_ABI fn abstract_options_end() {
const SAFE: ::arcdps::callbacks::OptionsCallback = #safe;

SAFE(::arcdps::__macro::ui())
}
Expand All @@ -152,8 +158,8 @@ impl ArcDpsGen {
quote! { abstract_imgui },
|safe, span| {
quote_spanned! {span=>
unsafe extern "C" fn abstract_imgui(loading: u32) {
const SAFE: ImguiCallback = #safe;
unsafe extern #C_ABI fn abstract_imgui(loading: ::std::primitive::u32) {
const SAFE: ::arcdps::callbacks::ImguiCallback = #safe;

SAFE(::arcdps::__macro::ui(), loading != 0)
}
Expand Down Expand Up @@ -187,20 +193,20 @@ impl ArcDpsGen {
/// Helper to generate a combat callback wrapper.
fn combat_wrapper(name: TokenStream, safe: &Expr, span: Span) -> TokenStream {
quote_spanned! {span=>
unsafe extern "C" fn #name(
unsafe extern #C_ABI fn #name(
event: *const ::arcdps::evtc::RawCombatEvent,
src: *const ::arcdps::evtc::RawAgent,
dst: *const ::arcdps::evtc::RawAgent,
skill_name: *const c_char,
id: u64,
revision: u64,
skill_name: *const ::arcdps::__macro::c_char,
id: ::std::primitive::u64,
revision: ::std::primitive::u64,
) {
const SAFE: CombatCallback = #safe;
const SAFE: ::arcdps::callbacks::CombatCallback = #safe;

SAFE(
event.as_ref().cloned().map(Into::into),
src.as_ref().map(Into::into),
dst.as_ref().map(Into::into),
event.as_ref().cloned().map(::std::convert::Into::into),
src.as_ref().map(::std::convert::Into::into),
dst.as_ref().map(::std::convert::Into::into),
::arcdps::__macro::str_from_cstr(skill_name),
id,
revision
Expand Down
Loading

0 comments on commit 75d5f3d

Please sign in to comment.