//! System lifecycle FFI functions. //! //! Provides opaque pointer wrappers for `entropyk_solver::System`. use std::os::raw::c_uint; use crate::components::EntropykComponent; use crate::error::EntropykErrorCode; /// Opaque handle to a thermodynamic system. /// /// Create with `entropyk_system_create()`. /// MUST call `entropyk_system_free()` when done. #[repr(C)] pub struct EntropykSystem { _private: [u8; 0], } impl EntropykSystem { fn from_inner(inner: entropyk_solver::System) -> *mut Self { Box::into_raw(Box::new(inner)) as *mut Self } } /// Create a new thermodynamic system. /// /// # Returns /// /// Pointer to the new system, or null on allocation failure. /// /// # Ownership /// /// Caller owns the returned pointer. MUST call `entropyk_system_free()` when done. #[no_mangle] pub extern "C" fn entropyk_system_create() -> *mut EntropykSystem { let system = entropyk_solver::System::new(); EntropykSystem::from_inner(system) } /// Free a system created by `entropyk_system_create()`. /// /// # Safety /// /// - `system` must be a valid pointer returned by `entropyk_system_create()`, or null /// - After this call, `system` is invalid and must not be used #[no_mangle] pub unsafe extern "C" fn entropyk_system_free(system: *mut EntropykSystem) { if !system.is_null() { drop(Box::from_raw(system as *mut entropyk_solver::System)); } } /// Add a component to the system. /// /// # Arguments /// /// - `system`: The system (must not be null) /// - `component`: The component to add (must not be null) /// /// # Returns /// /// Node index on success, or `UINT32_MAX` (0xFFFFFFFF) on error. /// Use this index for `entropyk_system_add_edge()`. /// /// # Safety /// /// - `system` must be a valid pointer /// - `component` must be a valid pointer /// - After this call, `component` is consumed and must not be used again #[no_mangle] pub unsafe extern "C" fn entropyk_system_add_component( system: *mut EntropykSystem, component: *mut EntropykComponent, ) -> c_uint { const ERROR_INDEX: c_uint = u32::MAX; if system.is_null() || component.is_null() { return ERROR_INDEX; } let sys = &mut *(system as *mut entropyk_solver::System); let comp_ptr = component as *mut Box; let comp = Box::from_raw(comp_ptr); let node_index = sys.add_component(*comp); node_index.index() as c_uint } /// Add a flow edge from source to target node. /// /// # Arguments /// /// - `system`: The system (must not be null) /// - `from`: Source node index (returned by `entropyk_system_add_component`) /// - `to`: Target node index (returned by `entropyk_system_add_component`) /// /// # Returns /// /// - `ENTROPYK_OK` on success /// - `ENTROPYK_NULL_POINTER` if system is null /// - `ENTROPYK_TOPOLOGY_ERROR` if edge cannot be added /// /// # Safety /// /// `system` must be a valid pointer. #[no_mangle] pub unsafe extern "C" fn entropyk_system_add_edge( system: *mut EntropykSystem, from: c_uint, to: c_uint, ) -> EntropykErrorCode { if system.is_null() { return EntropykErrorCode::EntropykNullPointer; } let sys = &mut *(system as *mut entropyk_solver::System); let src = petgraph::graph::NodeIndex::new(from as usize); let tgt = petgraph::graph::NodeIndex::new(to as usize); match sys.add_edge(src, tgt) { Ok(_) => EntropykErrorCode::EntropykOk, Err(e) => EntropykErrorCode::from(e), } } /// Finalize the system for solving. /// /// Must be called before any solve function. /// /// # Arguments /// /// - `system`: The system (must not be null) /// /// # Returns /// /// - `ENTROPYK_OK` on success /// - `ENTROPYK_NULL_POINTER` if system is null /// - `ENTROPYK_TOPOLOGY_ERROR` if topology is invalid /// /// # Safety /// /// `system` must be a valid pointer. #[no_mangle] pub unsafe extern "C" fn entropyk_system_finalize( system: *mut EntropykSystem, ) -> EntropykErrorCode { if system.is_null() { return EntropykErrorCode::EntropykNullPointer; } let sys = &mut *(system as *mut entropyk_solver::System); match sys.finalize() { Ok(_) => EntropykErrorCode::EntropykOk, Err(e) => EntropykErrorCode::from(e), } } /// Get the number of components (nodes) in the system. /// /// # Safety /// /// `system` must be a valid pointer or null. #[no_mangle] pub unsafe extern "C" fn entropyk_system_node_count(system: *const EntropykSystem) -> c_uint { if system.is_null() { return 0; } let sys = &*(system as *const entropyk_solver::System); sys.node_count() as c_uint } /// Get the number of edges in the system. /// /// # Safety /// /// `system` must be a valid pointer or null. #[no_mangle] pub unsafe extern "C" fn entropyk_system_edge_count(system: *const EntropykSystem) -> c_uint { if system.is_null() { return 0; } let sys = &*(system as *const entropyk_solver::System); sys.edge_count() as c_uint } /// Get the length of the state vector (after finalization). /// /// # Safety /// /// `system` must be a valid pointer or null. #[no_mangle] pub unsafe extern "C" fn entropyk_system_state_vector_len(system: *const EntropykSystem) -> c_uint { if system.is_null() { return 0; } let sys = &*(system as *const entropyk_solver::System); sys.state_vector_len() as c_uint }