Skip to main content

diffsol_c/
solution_wrapper_c.rs

1use crate::c_api_utils::{DIFFSOL_BAD_ARG, DIFFSOL_ERR, DIFFSOL_OK};
2use crate::host_array::HostArray;
3use crate::solution_wrapper::SolutionWrapper;
4use crate::{c_error, c_invalid_arg};
5
6fn boxed_host_array(array: HostArray) -> *mut HostArray {
7    Box::into_raw(Box::new(array))
8}
9
10fn boxed_host_array_list(arrays: Vec<HostArray>) -> (*mut *mut HostArray, usize) {
11    let boxed = arrays
12        .into_iter()
13        .map(boxed_host_array)
14        .collect::<Vec<_>>()
15        .into_boxed_slice();
16    let len = boxed.len();
17    let ptr = Box::into_raw(boxed) as *mut *mut HostArray;
18    (ptr, len)
19}
20
21/// Free a solution wrapper previously returned by this library.
22///
23/// # Safety
24/// `solution` must be either null or a pointer returned by this library that
25/// has not already been freed.
26#[unsafe(no_mangle)]
27pub unsafe extern "C" fn diffsol_solution_wrapper_free(solution: *mut SolutionWrapper) {
28    if solution.is_null() {
29        c_invalid_arg!("solution wrapper is null");
30        return;
31    }
32    unsafe {
33        drop(Box::from_raw(solution));
34    }
35}
36
37/// Return the recorded solution values as a host array.
38///
39/// # Safety
40/// `solution` must be a valid pointer created by this library. `out_array`
41/// must be a valid, writable pointer to receive ownership of the returned array.
42#[unsafe(no_mangle)]
43pub unsafe extern "C" fn diffsol_solution_wrapper_get_ys(
44    solution: *const SolutionWrapper,
45    out_array: *mut *mut HostArray,
46) -> i32 {
47    if solution.is_null() || out_array.is_null() {
48        c_invalid_arg!("invalid arguments to diffsol_solution_wrapper_get_ys");
49        return DIFFSOL_BAD_ARG;
50    }
51    let solution = unsafe { &*solution };
52    match solution.get_ys() {
53        Ok(array) => {
54            unsafe {
55                *out_array = boxed_host_array(array);
56            }
57            DIFFSOL_OK
58        }
59        Err(err) => {
60            c_error!(&format!("{}", err));
61            DIFFSOL_ERR
62        }
63    }
64}
65
66/// Return the recorded solution times as a host array.
67///
68/// # Safety
69/// `solution` must be a valid pointer created by this library. `out_array`
70/// must be a valid, writable pointer to receive ownership of the returned array.
71#[unsafe(no_mangle)]
72pub unsafe extern "C" fn diffsol_solution_wrapper_get_ts(
73    solution: *const SolutionWrapper,
74    out_array: *mut *mut HostArray,
75) -> i32 {
76    if solution.is_null() || out_array.is_null() {
77        c_invalid_arg!("invalid arguments to diffsol_solution_wrapper_get_ts");
78        return DIFFSOL_BAD_ARG;
79    }
80    let solution = unsafe { &*solution };
81    match solution.get_ts() {
82        Ok(array) => {
83            unsafe {
84                *out_array = boxed_host_array(array);
85            }
86            DIFFSOL_OK
87        }
88        Err(err) => {
89            c_error!(&format!("{}", err));
90            DIFFSOL_ERR
91        }
92    }
93}
94
95/// Return the recorded forward sensitivities as a list of host arrays.
96///
97/// # Safety
98/// `solution` must be a valid pointer created by this library. `out_sens` and
99/// `out_sens_len` must be valid, writable pointers to receive the result.
100#[unsafe(no_mangle)]
101pub unsafe extern "C" fn diffsol_solution_wrapper_get_sens(
102    solution: *const SolutionWrapper,
103    out_sens: *mut *mut *mut HostArray,
104    out_sens_len: *mut usize,
105) -> i32 {
106    if solution.is_null() || out_sens.is_null() || out_sens_len.is_null() {
107        c_invalid_arg!("invalid arguments to diffsol_solution_wrapper_get_sens");
108        return DIFFSOL_BAD_ARG;
109    }
110    let solution = unsafe { &*solution };
111    match solution.get_sens() {
112        Ok(sens) => {
113            let (sens_ptr, sens_len) = boxed_host_array_list(sens);
114            unsafe {
115                *out_sens = sens_ptr;
116                *out_sens_len = sens_len;
117            }
118            DIFFSOL_OK
119        }
120        Err(err) => {
121            c_error!(&format!("{}", err));
122            DIFFSOL_ERR
123        }
124    }
125}