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