lmflow/ffi/graph/
lifecycle.rs1#![allow(clippy::missing_safety_doc)]
2use super::*;
3
4#[no_mangle]
5pub extern "C" fn lmflow_graph_new() -> *mut LMFlowGraph {
6 guard_val(std::ptr::null_mut(), || {
7 last_error::set("");
10 Box::into_raw(Box::new(GraphSlot::default())) as *mut LMFlowGraph
11 })
12}
13
14#[no_mangle]
22pub unsafe extern "C" fn lmflow_graph_free(g: *mut LMFlowGraph) {
23 guard_val((), || {
24 if g.is_null() {
25 return;
26 }
27 let slot = Box::from_raw(g as *mut GraphSlot);
28 if let Some(gr) = &slot.graph {
29 gr.cancel();
30 let _ = gr.wait_done();
31 }
32 drop(slot);
33 });
34}
35
36#[no_mangle]
37pub unsafe extern "C" fn lmflow_graph_init_from_yaml(
38 g: *mut LMFlowGraph,
39 yaml: *const c_char,
40) -> i32 {
41 guard(|| {
42 let Some(slot) = slot_mut(g) else {
43 return fail(Error::InvalidArg("graph handle is null".into()));
44 };
45 if slot.graph.is_some() {
46 return fail(Error::State("graph already initialized".into()));
47 }
48 let Some(text) = cstr(yaml) else {
49 return fail(Error::InvalidArg("yaml is empty or not UTF-8".into()));
50 };
51 match Graph::from_yaml(text) {
52 Ok(gr) => {
53 slot.graph = Some(gr);
54 code::OK
55 }
56 Err(e) => fail(e),
57 }
58 })
59}
60
61#[no_mangle]
62pub unsafe extern "C" fn lmflow_graph_init_from_yaml_file(
63 g: *mut LMFlowGraph,
64 path: *const c_char,
65) -> i32 {
66 guard(|| {
67 let Some(slot) = slot_mut(g) else {
68 return fail(Error::InvalidArg("graph handle is null".into()));
69 };
70 if slot.graph.is_some() {
71 return fail(Error::State("graph already initialized".into()));
72 }
73 let Some(p) = cstr(path) else {
74 return fail(Error::InvalidArg("path is null".into()));
75 };
76 match Graph::from_yaml_file(p) {
77 Ok(gr) => {
78 slot.graph = Some(gr);
79 code::OK
80 }
81 Err(e) => fail(e),
82 }
83 })
84}
85
86#[no_mangle]
87pub unsafe extern "C" fn lmflow_graph_start(g: *mut LMFlowGraph) -> i32 {
88 guard(|| with_graph(g, |gr| to_status(gr.start())))
89}
90
91#[no_mangle]
94pub unsafe extern "C" fn lmflow_graph_reset(g: *mut LMFlowGraph) -> i32 {
95 guard(|| with_graph(g, |gr| to_status(gr.reset())))
96}
97
98#[no_mangle]
99pub unsafe extern "C" fn lmflow_graph_set_side_packet(
100 g: *mut LMFlowGraph,
101 name: *const c_char,
102 pkt: LMFlowPacket,
103) -> i32 {
104 guard(|| {
105 let p = take_packet(pkt);
106 let Some(n) = cstr(name) else {
107 return fail(Error::InvalidArg("side packet name is null".into()));
108 };
109 with_graph(g, |gr| to_status(gr.set_side_packet(n, p)))
110 })
111}
112
113#[no_mangle]
114pub unsafe extern "C" fn lmflow_graph_cancel(g: *mut LMFlowGraph) {
115 guard_val((), || {
116 let _ = with_graph(g, |gr| {
117 gr.cancel();
118 code::OK
119 });
120 });
121}
122
123#[no_mangle]
124pub unsafe extern "C" fn lmflow_graph_wait_done(g: *mut LMFlowGraph) -> i32 {
125 guard(|| with_graph(g, |gr| to_status(gr.wait_done())))
126}
127
128#[no_mangle]
129pub unsafe extern "C" fn lmflow_graph_wait_done_timeout(g: *mut LMFlowGraph, ms: i64) -> i32 {
130 guard(|| {
131 with_graph(g, |gr| {
132 to_status(gr.wait_done_timeout(std::time::Duration::from_millis(ms.max(0) as u64)))
133 })
134 })
135}
136
137#[no_mangle]
138pub unsafe extern "C" fn lmflow_graph_wait_until_idle(g: *mut LMFlowGraph) -> i32 {
139 guard(|| with_graph(g, |gr| to_status(gr.wait_until_idle())))
140}
141
142#[no_mangle]
143pub unsafe extern "C" fn lmflow_graph_wait_until_idle_timeout(g: *mut LMFlowGraph, ms: i64) -> i32 {
144 guard(|| {
145 with_graph(g, |gr| {
146 to_status(
147 gr.wait_until_idle_timeout(std::time::Duration::from_millis(ms.max(0) as u64)),
148 )
149 })
150 })
151}
152
153#[no_mangle]
154pub unsafe extern "C" fn lmflow_graph_pump_step(g: *mut LMFlowGraph) -> bool {
155 guard_val(false, || {
156 let Some(slot) = slot_mut(g) else {
157 last_error::set("graph handle is null");
158 return false;
159 };
160 let Some(graph) = slot.graph.as_ref() else {
161 last_error::set("graph not yet initialized");
162 return false;
163 };
164 graph.pump_step()
165 })
166}
167
168#[no_mangle]
169pub unsafe extern "C" fn lmflow_graph_pump_steps(g: *mut LMFlowGraph, max_steps: usize) -> usize {
170 guard_val(0, || {
171 let Some(slot) = slot_mut(g) else {
172 last_error::set("graph handle is null");
173 return 0;
174 };
175 let Some(graph) = slot.graph.as_ref() else {
176 last_error::set("graph not yet initialized");
177 return 0;
178 };
179 graph.pump_steps(max_steps)
180 })
181}
182
183#[no_mangle]
184pub unsafe extern "C" fn lmflow_graph_set_wakeup_callback(
185 g: *mut LMFlowGraph,
186 cb: Option<unsafe extern "C" fn(*mut c_void)>,
187 user: *mut c_void,
188) -> i32 {
189 guard(|| {
190 with_graph(g, |graph| {
191 if let Some(callback) = cb {
192 let user = user as usize;
193 graph.set_wakeup_callback(move || unsafe { callback(user as *mut c_void) });
194 } else {
195 graph.clear_wakeup_callback();
196 }
197 code::OK
198 })
199 })
200}
201
202#[no_mangle]
203pub unsafe extern "C" fn lmflow_graph_pause(g: *mut LMFlowGraph) {
204 guard_val((), || {
205 if let Some(gr) = graph_of(g) {
206 gr.pause();
207 }
208 });
209}
210
211#[no_mangle]
212pub unsafe extern "C" fn lmflow_graph_resume(g: *mut LMFlowGraph) {
213 guard_val((), || {
214 if let Some(gr) = graph_of(g) {
215 gr.resume();
216 }
217 });
218}
219
220#[no_mangle]
221pub unsafe extern "C" fn lmflow_graph_last_error(g: *mut LMFlowGraph) -> *const c_char {
222 guard_val(c"".as_ptr(), || {
223 match slot_mut(g).and_then(|s| s.graph.as_ref()) {
224 Some(gr) => gr.inner().shared.error_cstr(),
225 None => c"".as_ptr(),
226 }
227 })
228}
229
230#[no_mangle]
231pub unsafe extern "C" fn lmflow_graph_state(g: *mut LMFlowGraph) -> i32 {
232 guard_val(0, || match slot_mut(g).and_then(|s| s.graph.as_ref()) {
233 Some(gr) => gr.state() as i32,
234 None => State::Created as i32,
235 })
236}
237
238