annoy_rs/c_ffi/
mod.rs

1#[macro_use]
2mod macros;
3
4use crate::types::*;
5
6use libc::c_char;
7use std::error::Error;
8use std::ffi::CStr;
9use std::mem;
10use std::ptr;
11use std::slice;
12
13ffi_fn! {
14    fn load_annoy_index(path: *const c_char, dimension: i32, index_type: u8) -> *const AnnoyIndex {
15        let result = load_annoy_index_inner(path, dimension, index_type);
16        return match result {
17            Ok(ptr) => ptr,
18            Err(_e) => ptr::null(),
19        };
20    }
21}
22
23fn load_annoy_index_inner(
24    path: *const c_char,
25    dimension: i32,
26    index_type: u8,
27) -> Result<*const AnnoyIndex, Box<dyn Error>> {
28    let c_str_path = unsafe { CStr::from_ptr(path) };
29    let ru_path = c_str_path.to_str()?;
30    let ru_index_type: IndexType = unsafe { mem::transmute(index_type) };
31    let index = AnnoyIndex::load(dimension as usize, ru_path, ru_index_type)?;
32    return Ok(Box::into_raw(Box::new(index)));
33}
34
35ffi_fn! {
36    fn free_annoy_index(index: *const AnnoyIndex) {
37        unsafe { Box::from_raw(index as *mut AnnoyIndex); }
38    }
39}
40
41ffi_fn! {
42    fn get_dimension(index_ptr: *const AnnoyIndex) -> i32 {
43        let index = unsafe { &*index_ptr };
44        return index.dimension as i32;
45    }
46}
47
48ffi_fn! {
49    fn get_size(index_ptr: *const AnnoyIndex) -> u64 {
50        let index = unsafe { &*index_ptr };
51        return index.size as u64;
52    }
53}
54
55ffi_fn! {
56    fn get_item_vector(index_ptr: *const AnnoyIndex, item_index: u64, item_vector: *mut f32){
57        let index = unsafe{&*index_ptr};
58        let item_vec = index.get_item_vector(item_index);
59        let ptr = item_vec.as_ptr();
60        unsafe { ptr.copy_to(item_vector, index.dimension as usize) };
61    }
62}
63
64ffi_fn! {
65    fn get_nearest(
66        index_ptr: *const AnnoyIndex,
67        query_vector_ptr: *const f32,
68        n_results: u32,
69        search_k: i32,
70        should_include_distance: bool) -> *const AnnoyIndexSearchResult
71    {
72        let index = unsafe{&*index_ptr};
73        let query_vector = unsafe { slice::from_raw_parts(query_vector_ptr, index.dimension as usize) };
74        let result = index.get_nearest(query_vector, n_results as usize, search_k, should_include_distance);
75        return Box::into_raw(Box::new(result));
76    }
77}
78
79ffi_fn! {
80    fn get_nearest_to_item(
81        index_ptr: *const AnnoyIndex,
82        item_index: u64,
83        n_results: u32,
84        search_k: i32,
85        should_include_distance: bool,
86    ) -> *const AnnoyIndexSearchResult {
87        let index = unsafe { &*index_ptr };
88        let result =
89            index.get_nearest_to_item(item_index, n_results as usize, search_k, should_include_distance);
90        return Box::into_raw(Box::new(result));
91    }
92}
93
94ffi_fn! {
95    fn free_search_result(search_result_ptr: *const AnnoyIndexSearchResult){
96        unsafe { Box::from_raw(search_result_ptr as *mut AnnoyIndexSearchResult); }
97    }
98}
99
100ffi_fn! {
101    fn get_result_count(search_result_ptr: *const AnnoyIndexSearchResult) -> u64{
102        let search_result = unsafe{&*search_result_ptr};
103        return search_result.count as u64;
104    }
105}
106
107ffi_fn! {
108    fn get_id_list(search_result_ptr: *const AnnoyIndexSearchResult)->*const u64{
109        let search_result = unsafe{&*search_result_ptr};
110        return search_result.id_list.as_ptr();
111    }
112}
113
114ffi_fn! {
115    fn get_distance_list(search_result_ptr: *const AnnoyIndexSearchResult)->*const f32{
116        let search_result = unsafe{&*search_result_ptr};
117        return search_result.distance_list.as_ptr();
118    }
119}