macro_rules! export_ppp_callback {
{
$(
$vis:vis fn $cb_name:ident (
$(
$arg:ident : $arg_ty:ty
),* $(,)?
) $(-> $ret_ty:ty)?;
)*
} => { ... };
}Expand description
Declare and export a plugin-to-plugin (PPP) callback, which allows other plugins to add callbacks for this plugin to run.
ยงExample
For example, if you were writing a Rust plugin that would use a callback that runs every other basic block, you could declare and use two callbacks like so:
use panda::{Callback, export_ppp_callback};
use panda::prelude::*;
export_ppp_callback! {
pub(crate) fn on_every_even_block(cpu: &mut CPUState);
pub(crate) fn on_every_odd_block(cpu: &mut CPUState);
}
#[panda::init]
fn init() {
let mut i = 0;
Callback::new().before_block_exec(move |cpu, _| {
if i % 2 == 0 {
on_every_even_block::trigger(cpu);
} else {
on_every_odd_block::trigger(cpu);
}
i += 1;
});
}(For further usage see panda-rs/examples/ppp_callback_export.rs)
The return type of each callback can be any which implements CallbackReturn, a
trait which describes how to fold all the return values into a single return value
to be returned by <callback_name>::trigger(...). For example a callback that returns
a bool will return true if any of the callbacks return true, and will only return
false if every registered callback returns false.
If you wish to alter this behavior for existing types, use the newtype pattern, which will allow you to provide your own implementation by implementing the trait.
Note: All callback arguments and return values are expected to be FFI safe. If rustc
emits a warning for a given type, it is very likely it is not compatible with the
C ABI. In order to have your own custom types be FFI-safe, they should be marked
either #[repr(transparent)] or #[repr(C)] or should be treated as opaque types
(and thus should only be created and accessed within the same plugin and passed as
references).