bevy_mod_ffi_host_sys 0.2.0

Low-level FFI bindings for bevy_mod_ffi hosts
Documentation
use bevy::{
    ecs::{
        prelude::*,
        system::{DynSystemParam, SystemState},
        world::World,
    },
    prelude::*,
};
use bevy_mod_ffi_core::{dyn_system_param, system, system_state, world, RunSystemFn};

pub mod observer;
pub use observer::{CurrentLibraryHandle, LibraryHandle};

pub mod param;

pub type SharedSystem = Box<dyn System<In = In<SystemIn>, Out = ()>>;

pub type SharedSystemState = SystemState<(Vec<DynSystemParam<'static, 'static>>,)>;

pub struct SystemIn {
    pub input_ptr: *mut u8,
    pub output_ptr: *mut u8,
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn bevy_system_state_get(
    world_ptr: *mut world,
    state_ptr: *mut system_state,
    out_params: *mut *mut *mut dyn_system_param,
    out_params_len: *mut i32,
) {
    let bevy_world = unsafe { &mut *(world_ptr as *mut World) };
    let system_state = unsafe { &mut *(state_ptr as *mut SharedSystemState) };

    let params: Vec<DynSystemParam> = system_state.get_mut(bevy_world).0;

    let mut param_ptrs: Vec<*mut dyn_system_param> = Vec::new();
    for param in params {
        let boxed = Box::new(param);
        param_ptrs.push(Box::into_raw(boxed) as *mut dyn_system_param);
    }

    let len = param_ptrs.len();
    let pointers = param_ptrs.into_boxed_slice();

    unsafe {
        *out_params = Box::into_raw(pointers) as *mut *mut dyn_system_param;
        *out_params_len = len as i32;
    }
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn bevy_system_state_apply(
    world_ptr: *mut world,
    state_ptr: *mut system_state,
) {
    let world = unsafe { &mut *(world_ptr as *mut World) };

    let system_state = unsafe { &mut *(state_ptr as *mut SharedSystemState) };
    system_state.apply(world);
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn bevy_system_state_drop(state_ptr: *mut system_state) {
    let _ = unsafe { Box::from_raw(state_ptr as *mut SharedSystemState) };
}

#[unsafe(no_mangle)]
pub unsafe extern "C" fn bevy_system_state_build(
    state_ptr: *mut system_state,
    f_ptr: *mut (),
    run_system_fn: RunSystemFn,
    out_ptr: *mut *mut system,
) {
    let state: Box<SharedSystemState> = unsafe { Box::from_raw(state_ptr as _) };

    let f_ptr_n = f_ptr as usize;

    let bevy_system =
        state.build_system_with_input(move |input: In<SystemIn>, params: Vec<DynSystemParam>| {
            let mut param_ptrs: Vec<*mut dyn_system_param> = Vec::new();
            for param in params {
                let boxed = Box::new(param);
                param_ptrs.push(Box::into_raw(boxed) as *mut dyn_system_param);
            }
            let len = param_ptrs.len();
            let pointers_ptr = param_ptrs.as_ptr();

            unsafe {
                run_system_fn(
                    f_ptr_n as _,
                    pointers_ptr,
                    len,
                    input.input_ptr,
                    input.output_ptr,
                )
            };
        });

    let boxed: Box<SharedSystem> = Box::new(Box::new(bevy_system));
    unsafe {
        *out_ptr = Box::into_raw(boxed) as *mut system;
    }
}