lmflow/ffi/
kernel_runner.rs1use super::*;
2
3unsafe fn runner_ref<'a>(p: *mut LMFlowKernelRunner) -> Option<&'a mut KernelRunnerHandle> {
4 (!p.is_null()).then(|| &mut *(p as *mut KernelRunnerHandle))
5}
6
7#[no_mangle]
8pub unsafe extern "C" fn lmflow_kernel_runner_new(
9 kernel: *const c_char,
10 input_ports: usize,
11 output_ports: usize,
12) -> *mut LMFlowKernelRunner {
13 guard_val(std::ptr::null_mut(), || {
14 let Some(name) = cstr(kernel) else {
15 last_error::set("kernel name is null");
16 return std::ptr::null_mut();
17 };
18 match KernelRunner::new(name, input_ports, output_ports) {
19 Ok(runner) => {
20 Box::into_raw(Box::new(KernelRunnerHandle { runner })) as *mut LMFlowKernelRunner
21 }
22 Err(error) => {
23 last_error::set(&error.to_string());
24 std::ptr::null_mut()
25 }
26 }
27 })
28}
29
30#[no_mangle]
31pub unsafe extern "C" fn lmflow_kernel_runner_free(p: *mut LMFlowKernelRunner) {
32 guard_val((), || {
33 if !p.is_null() {
34 drop(Box::from_raw(p as *mut KernelRunnerHandle));
35 }
36 });
37}
38
39#[no_mangle]
40pub unsafe extern "C" fn lmflow_kernel_runner_start(p: *mut LMFlowKernelRunner) -> i32 {
41 guard(|| {
42 let Some(handle) = runner_ref(p) else {
43 return fail(Error::InvalidArg("kernel runner handle is null".into()));
44 };
45 to_status(handle.runner.open())
46 })
47}
48
49#[no_mangle]
50pub unsafe extern "C" fn lmflow_kernel_runner_set_options_json(
51 p: *mut LMFlowKernelRunner,
52 json: *const c_char,
53) -> i32 {
54 guard(|| {
55 let Some(handle) = runner_ref(p) else {
56 return fail(Error::InvalidArg("kernel runner handle is null".into()));
57 };
58 let Some(json) = cstr(json) else {
59 return fail(Error::InvalidArg(
60 "options JSON is null or invalid UTF-8".into(),
61 ));
62 };
63 to_status(handle.runner.set_options_json(json))
64 })
65}
66
67#[no_mangle]
68pub unsafe extern "C" fn lmflow_kernel_runner_set_side_packet(
69 p: *mut LMFlowKernelRunner,
70 name: *const c_char,
71 packet: LMFlowPacket,
72) -> i32 {
73 guard(|| {
74 let owned = take_packet(packet);
75 let Some(handle) = runner_ref(p) else {
76 return fail(Error::InvalidArg("kernel runner handle is null".into()));
77 };
78 let Some(name) = cstr(name) else {
79 return fail(Error::InvalidArg("side packet name is null".into()));
80 };
81 to_status(handle.runner.set_side_packet(name, owned))
82 })
83}
84
85#[no_mangle]
86pub unsafe extern "C" fn lmflow_kernel_runner_add_input(
87 p: *mut LMFlowKernelRunner,
88 port: usize,
89 packet: LMFlowPacket,
90) -> i32 {
91 guard(|| {
92 let owned = take_packet(packet);
93 let Some(handle) = runner_ref(p) else {
94 return fail(Error::InvalidArg("kernel runner handle is null".into()));
95 };
96 to_status(handle.runner.add_input(port, owned))
97 })
98}
99
100#[no_mangle]
101pub unsafe extern "C" fn lmflow_kernel_runner_process(
102 p: *mut LMFlowKernelRunner,
103 timestamp: i64,
104) -> i32 {
105 guard(|| {
106 let Some(handle) = runner_ref(p) else {
107 return fail(Error::InvalidArg("kernel runner handle is null".into()));
108 };
109 match handle
110 .runner
111 .process_pending(crate::timestamp::Timestamp(timestamp))
112 {
113 Ok(_) => code::OK,
114 Err(error) => fail(error),
115 }
116 })
117}
118
119#[no_mangle]
120pub unsafe extern "C" fn lmflow_kernel_runner_try_next(
121 p: *mut LMFlowKernelRunner,
122 port: usize,
123 out: *mut LMFlowPacket,
124) -> i32 {
125 guard(|| {
126 let Some(handle) = runner_ref(p) else {
127 return fail(Error::InvalidArg("kernel runner handle is null".into()));
128 };
129 match handle.runner.try_output(port) {
130 Ok(Some(packet)) => {
131 if !out.is_null() {
132 *out = own_packet(packet);
133 }
134 code::OK
135 }
136 Ok(None) => code::WOULD_BLOCK,
137 Err(error) => fail(error),
138 }
139 })
140}
141
142#[no_mangle]
143pub unsafe extern "C" fn lmflow_kernel_runner_close(p: *mut LMFlowKernelRunner) -> i32 {
144 guard(|| {
145 let Some(handle) = runner_ref(p) else {
146 return fail(Error::InvalidArg("kernel runner handle is null".into()));
147 };
148 match handle.runner.close() {
149 Ok(_) => code::OK,
150 Err(error) => fail(error),
151 }
152 })
153}