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