viam_rust_utils/ffi/spatialmath/vector3.rs
1use ffi_helpers::null_pointer_check;
2use libc::c_double;
3
4use nalgebra::Vector3;
5
6/// The FFI interface wrapping the nalgebra crate for Vector functions and
7/// initialization. All public functions are meant to be called externally
8/// from other languages
9
10/// Allocates the vector to the heap with a stable memory address and
11/// returns the raw pointer (for use by the FFI interface)
12pub(crate) fn to_raw_pointer(vec: Vector3<f64>) -> *mut Vector3<f64> {
13 Box::into_raw(Box::new(vec))
14}
15
16/// Initialize a 3-vector from raw components and retrieve the C pointer
17/// to its address.
18///
19/// # Safety
20///
21/// When finished with the underlying vector initialized by this function
22/// the caller must remember to free the vector memory using the
23/// free_vector_memory FFI function
24#[no_mangle]
25pub extern "C" fn new_vector3(x: f64, y: f64, z: f64) -> *mut Vector3<f64> {
26 let new_vec = Vector3::new(x, y, z);
27 to_raw_pointer(new_vec)
28}
29
30/// Free memory at the address of the vector pointer.
31///
32/// # Safety
33/// Outer processes that work with Vectors via the FFI interface MUST remember
34/// to call this function when finished with a vector
35#[no_mangle]
36pub unsafe extern "C" fn free_vector_memory(ptr: *mut Vector3<f64>) {
37 if ptr.is_null() {
38 return;
39 }
40 let _ = Box::from_raw(ptr);
41}
42
43/// Get the components of a vector as a list of C doubles, the order of the
44/// components will be (x, y, z).
45///
46/// # Safety
47///
48/// When finished with the underlying vector, the caller must remember to
49/// free the vector memory using the free_vector_memory FFI function
50#[no_mangle]
51pub unsafe extern "C" fn vector_get_components(vec_ptr: *const Vector3<f64>) -> *const c_double {
52 null_pointer_check!(vec_ptr);
53 let components: [c_double; 3] = [(&(*vec_ptr))[0], (&(*vec_ptr))[1], (&(*vec_ptr))[2]];
54 Box::into_raw(Box::new(components)) as *const _
55}
56
57/// Set the x component of an existing vector stored at the address
58/// of a pointer.
59///
60/// # Safety
61///
62/// When finished with the underlying vector, the caller must remember to
63/// free the vector memory using the free_vector_memory FFI function
64#[no_mangle]
65pub unsafe extern "C" fn vector_set_x(vec_ptr: *mut Vector3<f64>, x_val: f64) {
66 null_pointer_check!(vec_ptr);
67 (&mut (*vec_ptr))[0] = x_val;
68}
69
70/// Set the y component of an existing vector stored at the address
71/// of a pointer.
72///
73/// # Safety
74///
75/// When finished with the underlying vector, the caller must remember to
76/// free the vector memory using the free_vector_memory FFI function
77#[no_mangle]
78pub unsafe extern "C" fn vector_set_y(vec_ptr: *mut Vector3<f64>, y_val: f64) {
79 null_pointer_check!(vec_ptr);
80 (&mut (*vec_ptr))[1] = y_val;
81}
82
83/// Set the z component of an existing vector stored at the address
84/// of a pointer.
85///
86/// # Safety
87///
88/// When finished with the underlying vector, the caller must remember to
89/// free the vector memory using the free_vector_memory FFI function
90#[no_mangle]
91pub unsafe extern "C" fn vector_set_z(vec_ptr: *mut Vector3<f64>, z_val: f64) {
92 null_pointer_check!(vec_ptr);
93 (&mut (*vec_ptr))[2] = z_val;
94}
95
96/// Normalizes an existing vector stored at the address of
97/// a pointer (vec_ptr)
98///
99/// # Safety
100///
101/// When finished with the underlying vector, the caller must remember to
102/// free the vector memory using the free_vector_memory FFI function
103#[no_mangle]
104pub unsafe extern "C" fn normalize_vector(vec_ptr: *mut Vector3<f64>) {
105 null_pointer_check!(vec_ptr);
106 (*vec_ptr).normalize_mut();
107}
108
109/// Initializes a normalized copy of a vector stored at the
110/// address of a pointer (vec_ptr) and returns a pointer to the
111/// memory of the result
112///
113/// # Safety
114///
115/// The caller must remember to free the vector memory of *both* the input and
116/// output vectors when finished with them using the free_vector_memory FFI function
117#[no_mangle]
118pub unsafe extern "C" fn vector_get_normalized(vec_ptr: *const Vector3<f64>) -> *mut Vector3<f64> {
119 null_pointer_check!(vec_ptr);
120 let vec = (*vec_ptr).normalize();
121 to_raw_pointer(vec)
122}
123
124/// Scales an existing vector stored at the address of
125/// a pointer (vec_ptr) by a float factor
126///
127/// # Safety
128///
129/// When finished with the underlying vector, the caller must remember to
130/// free the vector memory using the free_vector_memory FFI function
131#[no_mangle]
132pub unsafe extern "C" fn scale_vector(vec_ptr: *mut Vector3<f64>, factor: f64) {
133 null_pointer_check!(vec_ptr);
134 (*vec_ptr).scale_mut(factor);
135}
136
137/// Initializes a scaled copy of a vector stored at the
138/// address of a pointer (vec_ptr) and returns a pointer to the
139/// memory of the result
140///
141/// # Safety
142///
143/// The caller must remember to free the vector memory of *both* the input and
144/// output vectors when finished with them using the free_vector_memory FFI function
145#[no_mangle]
146pub unsafe extern "C" fn vector_get_scaled(
147 vec_ptr: *const Vector3<f64>,
148 factor: f64,
149) -> *mut Vector3<f64> {
150 null_pointer_check!(vec_ptr);
151 let vec = (*vec_ptr).scale(factor);
152 to_raw_pointer(vec)
153}
154
155/// Adds two vectors and returns a pointer to the
156/// memory of the result
157///
158/// # Safety
159///
160/// The caller must remember to free the vector memory of *both* the input and
161/// output vectors when finished with them using the free_vector_memory FFI function
162#[no_mangle]
163pub unsafe extern "C" fn vector_add(
164 vec_ptr_1: *const Vector3<f64>,
165 vec_ptr_2: *const Vector3<f64>,
166) -> *mut Vector3<f64> {
167 null_pointer_check!(vec_ptr_1);
168 null_pointer_check!(vec_ptr_2);
169 to_raw_pointer((*vec_ptr_1) + (*vec_ptr_2))
170}
171
172/// Subtracts two vectors and returns a pointer to the
173/// memory of the result
174///
175/// # Safety
176///
177/// The caller must remember to free the vector memory of *both* the input and
178/// output vectors when finished with them using the free_vector_memory FFI function
179#[no_mangle]
180pub unsafe extern "C" fn vector_subtract(
181 vec_ptr_1: *const Vector3<f64>,
182 vec_ptr_2: *const Vector3<f64>,
183) -> *mut Vector3<f64> {
184 null_pointer_check!(vec_ptr_1);
185 null_pointer_check!(vec_ptr_2);
186 to_raw_pointer((*vec_ptr_1) - (*vec_ptr_2))
187}
188
189/// Computes the dot product of two vectors
190///
191/// # Safety
192///
193/// The caller must remember to free the vector memory of the input vectors
194/// when finished with them using the free_vector_memory FFI function
195#[no_mangle]
196pub unsafe extern "C" fn vector_dot_product(
197 vec_ptr_1: *const Vector3<f64>,
198 vec_ptr_2: *const Vector3<f64>,
199) -> f64 {
200 null_pointer_check!(vec_ptr_1, f64::NAN);
201 null_pointer_check!(vec_ptr_2, f64::NAN);
202 (*vec_ptr_1).dot(&*vec_ptr_2)
203}
204
205/// Computes the cross product of two vectors and returns
206/// a pointer to the memory of the result
207///
208/// # Safety
209///
210/// The caller must remember to free the vector memory of *both* the input and
211/// output vectors when finished with them using the free_vector_memory FFI function
212#[no_mangle]
213pub unsafe extern "C" fn vector_cross_product(
214 vec_ptr_1: *mut Vector3<f64>,
215 vec_ptr_2: *mut Vector3<f64>,
216) -> *mut Vector3<f64> {
217 null_pointer_check!(vec_ptr_1);
218 null_pointer_check!(vec_ptr_2);
219 let vec = (*vec_ptr_1).cross(&*vec_ptr_2);
220 to_raw_pointer(vec)
221}
222
223/// Free memory of an array of vector components at the given address.
224///
225/// # Safety
226///
227/// Outer processes that request the components of a vector should call this function
228/// to free the memory allocated to the array once finished
229#[no_mangle]
230pub unsafe extern "C" fn free_vector_components(ptr: *mut c_double) {
231 if ptr.is_null() {
232 return;
233 }
234 let ptr = ptr as *mut [c_double; 3];
235 let _: Box<[c_double; 3]> = Box::from_raw(ptr);
236}