Macro detour::static_detours
[−]
[src]
macro_rules! static_detours { (@parse_attributes ($($input:tt)*) | $(#[$attribute:meta])* $next:tt $($rest:tt)*) => { ... }; (@parse_access_modifier ($($input:tt)*) | pub struct $($rest:tt)*) => { ... }; (@parse_access_modifier ($($input:tt)*) | struct $($rest:tt)*) => { ... }; (@parse_name ($($input:tt)*) | $name:ident : $($rest:tt)*) => { ... }; (@parse_unsafe ($($input:tt)*) | unsafe $($rest:tt)*) => { ... }; (@parse_unsafe ($($input:tt)*) | $($rest:tt)*) => { ... }; (@parse_calling_convention ($($input:tt)*) ($($modifier:tt)*) | extern $cc:tt fn $($rest:tt)*) => { ... }; (@parse_calling_convention ($($input:tt)*) ($($modifier:tt)*) | extern fn $($rest:tt)*) => { ... }; (@parse_calling_convention ($($input:tt)*) ($($modifier:tt)*) | fn $($rest:tt)*) => { ... }; (@parse_prototype ($($input:tt)*) | ($($argument_type:ty),*) -> $return_type:ty ; $($rest:tt)*) => { ... }; (@parse_prototype ($($input:tt)*) | ($($argument_type:ty),*) $($rest:tt)*) => { ... }; (@parse_terminator ($($input:tt)*) | ; $($rest:tt)*) => { ... }; (@parse_entries ($($input:tt)*) | $($rest:tt)+) => { ... }; (@parse_entries ($($input:tt)*) | ) => { ... }; (@aggregate ($($attribute:meta)*) ($($visibility:tt)*) ($name:ident) ($($modifier:tt)*) ($($argument_type:ty)*) ($return_type:ty)) => { ... }; (@create_detour ($($argument_name:ident)*) ($($attribute:meta)*) ($($visibility:tt)*) ($name:ident) ($($modifier:tt)*) ($($argument_type:ty)*) ($return_type:ty) ($fn_type:ty)) => { ... }; (@argument_names ($label:ident) ($($input:tt)*) ($($token:tt)*)) => { ... }; (@argument_names ($label:ident) ($($input:tt)*) ($hd_name:tt $($tl_name:tt)*) ($hd:tt $($tl:tt)*) ($($acc:tt)*) ) => { ... }; (@argument_names ($label:ident) ($($input:tt)*) ($($name:tt)*) () ($($acc:tt)*)) => { ... }; (@generate $item:item) => { ... }; ($($t:tt)+) => { ... }; }
A macro for defining type-safe detours.
This macro creates a StaticDetourController
, which returns a StaticDetour
upon initialization. It can accept both functions and closures as its second
argument. Due to the requirements of the implementation, const_fn is needed
if the macro is to be used.
A static detour may only have one active detour at a time. Therefore another
initialize
call can only be done once the previous instance has been
dropped. This is because the closures are being stored as static variables.
Example
#![feature(const_fn, const_atomic_ptr_new, const_ptr_null_mut)] #[macro_use] extern crate detour; use detour::Detour; static_detours! { struct Test: /* extern "X" */ fn(i32) -> i32; } fn add5(val: i32) -> i32 { val + 5 } fn add10(val: i32) -> i32 { val + 10 } fn main() { let mut hook = unsafe { Test.initialize(add5, add10).unwrap() }; assert_eq!(add5(1), 6); assert_eq!(hook.call(1), 6); unsafe { hook.enable().unwrap(); } assert_eq!(add5(1), 11); assert_eq!(hook.call(1), 6); // You can also call using the static object assert_eq!(unsafe { Test.get().unwrap().call(1) }, 6); // ... and change the detour whilst hooked hook.set_detour(|val| val - 5); assert_eq!(add5(5), 0); unsafe { hook.disable().unwrap() }; assert_eq!(add5(1), 6); }
Any type of function is supported, and extern is optional.