Skip to main content

lmflow/ffi/graph/
mod.rs

1//! C ABI:图:生命周期、输入口、poller/observer、内省
2//!
3//! 由 [`super`](../index.html) 的分节拆出 —— 见 `ffi/mod.rs` 的模块头注释,
4//! 那里定义了整层的约定(catch_unwind 包裹、last_error、空指针检查、布局钉死)。
5#![allow(clippy::missing_safety_doc)]
6
7use std::ffi::c_void;
8
9use crate::graph::{Graph, Poller, State};
10use crate::runtime;
11use crate::status::Error;
12
13use super::*;
14
15mod diagnostics;
16mod input_poller;
17mod lifecycle;
18mod observer;
19
20pub use diagnostics::*;
21pub use input_poller::*;
22pub use lifecycle::*;
23pub use observer::*;
24
25/// `lmflow_graph_new` 先返回一个空槽,`init_from_yaml` 才真正建图。
26///
27/// 输入/输出句柄(`LMFlowInput*`/`LMFlowPoller*`)**不**由本槽持有 —— 它们是**调用方拥有**的:
28/// `lmflow_graph_input`/`lmflow_graph_add_poller` 返回一个独立的 `Box::into_raw` 句柄,
29/// 各自持一份 `Arc<GraphInner>`,须由调用方 `lmflow_input_free`/`lmflow_poller_free` 释放。
30/// 这样即使先 `lmflow_graph_free` 了图,句柄内存依旧有效(其 Arc 撑着引擎),
31/// 之后再用只会得到「图已结束」的错误,而不是 use-after-free。
32#[derive(Default)]
33pub struct GraphSlot {
34    graph: Option<Graph>,
35}
36
37unsafe fn slot_mut<'a>(g: *mut LMFlowGraph) -> Option<&'a mut GraphSlot> {
38    if g.is_null() {
39        None
40    } else {
41        Some(&mut *(g as *mut GraphSlot))
42    }
43}
44
45unsafe fn with_graph<F: FnOnce(&Graph) -> i32>(g: *mut LMFlowGraph, f: F) -> i32 {
46    match slot_mut(g).and_then(|s| s.graph.as_ref()) {
47        Some(gr) => f(gr),
48        None => fail(Error::State("graph not yet initialized".into())),
49    }
50}
51
52// Shared graph handle lookup used by submodules.
53pub(super) unsafe fn graph_of<'a>(g: *mut LMFlowGraph) -> Option<&'a Graph> {
54    slot_mut(g).and_then(|s| s.graph.as_ref())
55}