Thanks to visit codestin.com
Credit goes to docs.rs

arrayfire/core/
error.rs

1use super::defines::AfError;
2use super::util::{dim_t, free_host};
3
4use libc::c_char;
5use std::ffi::CStr;
6use std::ops::{Deref, DerefMut};
7use std::sync::RwLock;
8
9extern "C" {
10    fn af_get_last_error(str: *mut *mut c_char, len: *mut dim_t);
11}
12
13/// Signature of error handling callback function
14pub type ErrorCallback = fn(AfError);
15
16/// Structure holding handle to callback function
17pub struct Callback {
18    cb: ErrorCallback,
19}
20
21impl Callback {
22    /// Associated function to create a new Callback object
23    pub fn new(callback: ErrorCallback) -> Self {
24        Self { cb: callback }
25    }
26
27    /// call invokes the error callback with `error_code`.
28    pub fn call(&self, error_code: AfError) {
29        (self.cb)(error_code)
30    }
31}
32
33/// Default error handling callback provided by ArrayFire crate
34pub fn handle_error_general(error_code: AfError) {
35    match error_code {
36        AfError::SUCCESS => {} /* No-op */
37        _ => panic!(
38            "Error message: {}\nLast error: {}",
39            error_code,
40            get_last_error()
41        ),
42    }
43}
44
45lazy_static! {
46    static ref ERROR_HANDLER_LOCK: RwLock<Callback> =
47        RwLock::new(Callback::new(handle_error_general));
48}
49
50/// Register user provided error handler
51///
52/// # Examples
53/// ```
54/// #[macro_use]
55/// extern crate arrayfire;
56///
57/// use arrayfire::{AfError, Callback, info, register_error_handler};
58/// use std::error::Error;
59///
60/// fn handle_error(error_code: AfError) {
61///     match error_code {
62///         AfError::SUCCESS => {}, /* No-op */
63///         _ => panic!("Error message: {}", error_code),
64///     }
65/// }
66///
67/// fn main() {
68///     //Registering the error handler should be the first call
69///     //before any other functions are called if your version
70///     //of error is to be used for subsequent function calls
71///     register_error_handler(Callback::new(handle_error));
72///
73///     info();
74/// }
75/// ```
76#[allow(clippy::match_wild_err_arm)]
77pub fn register_error_handler(cb_value: Callback) {
78    let mut gaurd = match ERROR_HANDLER_LOCK.write() {
79        Ok(g) => g,
80        Err(_) => panic!("Failed to acquire lock to register error handler"),
81    };
82
83    *gaurd.deref_mut() = cb_value;
84}
85
86/// Default error handler for error code returned by ArrayFire FFI calls
87#[allow(non_snake_case)]
88#[allow(clippy::match_wild_err_arm)]
89pub fn HANDLE_ERROR(error_code: AfError) {
90    let gaurd = match ERROR_HANDLER_LOCK.read() {
91        Ok(g) => g,
92        Err(_) => panic!("Failed to acquire lock while handling FFI return value"),
93    };
94
95    (*gaurd.deref()).call(error_code);
96}
97
98/// Fetch last error description as String
99pub fn get_last_error() -> String {
100    let mut result: String = String::from("No Last Error");
101    let mut tmp: *mut c_char = ::std::ptr::null_mut();
102    let mut len: dim_t = 0;
103    unsafe {
104        af_get_last_error(&mut tmp, &mut len as *mut dim_t);
105        if len > 0 {
106            result = CStr::from_ptr(tmp).to_string_lossy().into_owned();
107            free_host(tmp);
108        }
109    }
110    result
111}