1use crate::map::{IndexType, MapManager};
2use tokio::runtime::{Runtime, Builder};
3use std::os::raw::c_char;
4use std::sync::{Once};
5
6pub mod astar;
7pub mod errors;
8pub mod id;
9pub mod map;
10pub mod rmacro;
11
12#[repr(C)] pub struct CPoint {
14 pub x: i32,
15 pub y: i32,
16}
17
18#[repr(C)]
19pub struct CPointArray {
20 length: usize,
21 data: *const (i32,i32),
22 cap: usize,
23}
24
25static TOKIO_RUNTIME_INIT: Once = Once::new();
26static mut TOKIO_RUNTIME: Option<Runtime> = None;
27
28pub fn init_tokio_runtime(worker_threads: usize) {
30 TOKIO_RUNTIME_INIT.call_once(|| {
31 unsafe {
32 TOKIO_RUNTIME = Some(
33 Builder::new_multi_thread()
34 .worker_threads(worker_threads)
35 .build()
36 .unwrap()
37 );
38 }
39 });
40}
41
42pub fn get_tokio_runtime() -> &'static Runtime {
43 unsafe {
44 TOKIO_RUNTIME.as_ref().unwrap()
45 }
46}
47
48#[no_mangle]
50pub extern "C" fn init_runtime(worker_threads: usize) {
51 init_tokio_runtime(worker_threads);
52}
53
54#[no_mangle]
55pub extern "C" fn find_path(map_id:i64, start_point:&CPoint, end_point:&CPoint) -> CPointArray {
56 get_tokio_runtime().block_on(async {
57 find(map_id, start_point, end_point).await
58 })
59}
60
61#[no_mangle]
62pub extern "C" fn set_walkable(map_id:i64, point:&CPoint, walkable:i32) -> bool {
63 get_tokio_runtime().block_on(async {
64 set_walkable_impl(map_id, point, walkable).await
65 })
66}
67
68#[allow(clippy::not_unsafe_ptr_arg_deref)]
69#[no_mangle]
70pub extern "C" fn load_map(c_string: *const c_char) -> i64 {
71 let map_file = unsafe { std::ffi::CStr::from_ptr(c_string) };
72 get_tokio_runtime().block_on(async {
73 load_map_from_file(map_file.to_string_lossy().into_owned()).await
74 })
75}
76
77#[allow(clippy::not_unsafe_ptr_arg_deref)]
78#[no_mangle]
79pub extern "C" fn load_map_from_string(file_content: *const c_char) -> i64 {
80 let map_file_content = unsafe { std::ffi::CStr::from_ptr(file_content) };
81 get_tokio_runtime().block_on(async {
82 load_map_from_file_content(map_file_content.to_string_lossy().into_owned()).await
83 })
84}
85
86#[no_mangle]
87pub extern "C" fn free_path(path: CPointArray) {
88 free_array(path);
89}
90
91async fn load_map_from_file(map_file: String) -> i64 {
92 let map = MapManager::get_instance();
93
94 let map_id = map.write().await.new_astar().await;
96
97 let _ = match map.read().await.load_from_file(&map_id, map_file.to_string()).await {
98 Ok(_) => map_id,
99 Err(err) => {println!("{}", err);0}
100 }; map_id
101}
102
103async fn load_map_from_file_content(file_content: String) -> i64 {
104 let map = MapManager::get_instance();
105
106 let map_id = map.write().await.new_astar().await;
108
109 let _ = match map.read().await.load_from_string(&map_id, file_content).await {
110 Ok(_) => map_id,
111 Err(err) => {println!("{}", err);0}
112 }; map_id
113}
114
115async fn find(map_id:i64, start_point:&CPoint, end_point:&CPoint) -> CPointArray {
116 let map = MapManager::get_instance();
117
118 let result = map.read().await.find_path(&map_id,(start_point.x, start_point.y), (end_point.x, end_point.y)).await;
120
121 match result {
122 Ok(v) => convert_to_c_array(v),
123 Err(_e) => CPointArray{ data: &(0, 0), length: 0, cap: 0 },
124 }
125}
126
127async fn set_walkable_impl(map_id:i64, point:&CPoint, walkable:i32) -> bool {
128 let map = MapManager::get_instance();
129 let result = map.write().await.set_walkable(&map_id, (point.x, point.y), walkable).await;
131 result.is_ok()
132}
133
134fn convert_to_c_array(mut vec: Vec<(IndexType, IndexType)>) -> CPointArray {
135 let ptr = vec.as_mut_ptr();
136 let len = vec.len();
137 let cap = vec.capacity();
138
139 std::mem::forget(vec);
141
142 CPointArray {
143 data: ptr,
144 length: len,
145 cap
146 }
147}
148
149fn free_array(vec:CPointArray) {
150 let xx:Vec<(IndexType, IndexType)> = unsafe { Vec::from_raw_parts(vec.data as *mut (IndexType, IndexType), vec.length, vec.cap) };
151 drop(xx);
152}