directcpp/
lib.rs

1use std::future::Future;
2use std::marker::PhantomData;
3use std::pin::Pin;
4use std::sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}};
5use std::task::{Context, Poll};
6/// Generate bridge code for C++ functions.
7/// # Examples
8/// ```
9/// use directcpp::bridge;
10/// #[bridge]
11/// extern "C++" {
12/// 	pub fn on_start();
13/// }
14/// ```
15/// This generates the following code:
16/// ```
17/// extern "C" {
18///     #[link_name = "?on_start@@YAXXZ"]
19///     fn ffi__on_start();
20/// }
21/// pub fn on_start() { unsafe { ffi__on_start() } }
22/// ```
23/// See the [README](https://github.com/swigger/directcpp/) for more details.
24pub use directcpp_macro::bridge;
25
26/// Allow link to msvc debug runtime.
27/// # Examples
28/// ```
29/// use directcpp::enable_msvc_debug;
30/// #[enable_msvc_debug]
31/// struct UnusedStruct;
32/// ```
33/// This generates nothing, but it works silently background in a hacker's way.
34///
35pub use directcpp_macro::enable_msvc_debug;
36
37// implies the value is POD so no dtor is needed, it's just copied.
38#[doc(hidden)]
39pub struct POD<T>(T);
40
41#[doc(hidden)]
42pub trait ManDtor {
43	unsafe fn __dtor(ptr: *mut [u8;0]);
44}
45
46#[doc(hidden)]
47pub trait DropSP {
48	unsafe fn __drop_sp(sp_ptr: *mut [u8;0]);
49}
50
51#[repr(C)]
52pub struct SharedPtr<T> where T: DropSP {
53	val1: usize,
54	val2: usize,
55    _phantom: PhantomData<T>,
56}
57impl<T> Default for SharedPtr<T> where T: DropSP {
58	fn default() -> Self {
59		Self {
60			val1: 0,
61			val2: 0,
62			_phantom: PhantomData,
63		}
64	}
65}
66impl<T> Drop for SharedPtr<T> where T: DropSP {
67	fn drop(&mut self) {
68		unsafe {
69			T::__drop_sp(self as *mut SharedPtr<T> as *mut [u8;0]);
70		}
71	}
72}
73
74#[repr(C)]
75pub struct UniquePtr<T> where T: ManDtor {
76	val1: usize,
77	_phantom: PhantomData<T>,
78}
79impl<T> Default for UniquePtr<T> where T: ManDtor {
80	fn default() -> Self {
81		Self {
82			val1: 0,
83			_phantom: PhantomData,
84		}
85	}
86}
87impl<T> Drop for UniquePtr<T> where T: ManDtor {
88	fn drop(&mut self) {
89		unsafe {
90			if self.val1 != 0 {
91				T::__dtor(self.val1 as *mut [u8; 0]);
92			}
93		}
94	}
95}
96
97#[repr(C)]
98#[derive(Clone, Debug, Default)]
99pub struct CPtr<T> {
100	pub addr: usize,
101	_phantom: PhantomData<T>,
102}
103
104pub trait AsCPtr<T> {
105	fn as_cptr(&self) -> CPtr<T>;
106}
107
108impl<T> AsCPtr<T>  for SharedPtr<T>
109	where T:DropSP
110{
111	fn as_cptr(&self) -> CPtr<T> {
112		CPtr::<T> {
113			addr: self.val1,
114			_phantom: PhantomData
115		}
116	}
117}
118
119impl<T> AsCPtr<T> for UniquePtr<T>
120	where T: ManDtor
121{
122	fn as_cptr(&self) -> CPtr<T> {
123		CPtr::<T> {
124			addr: self.val1,
125			_phantom: PhantomData
126		}
127	}
128}
129
130#[repr(C)]
131struct FutureValueInner<T> {
132	f_set_value: fn(usize, &T),
133	value: Mutex<(Option<T>, Option<std::task::Waker>)>
134}
135pub struct FutureValue<T> {
136	value: Arc<FutureValueInner<T>>
137}
138
139impl<T> Future for FutureValue<T> {
140	type Output = T;
141
142	fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
143		let mut lock = self.value.value.lock().unwrap();
144		match lock.0.take() {
145			Some(ss) => Poll::Ready(ss),
146			None => {
147				lock.1 = Some(cx.waker().clone());
148				Poll::Pending
149			}
150		}
151	}
152}
153
154impl<T> Default for FutureValue<T> where T:Clone {
155	fn default() -> Self {
156		Self {
157			value: Arc::new(FutureValueInner {
158				f_set_value: Self::set_value,
159				value: Mutex::new((None, None))
160			})
161		}
162	}
163}
164
165impl<T> FutureValue<T> where T: Clone {
166	pub unsafe fn to_ptr(&mut self) -> usize {
167		let p1 = self as *mut Self as *mut *mut AtomicUsize;
168		(**p1).fetch_add(1, Ordering::Relaxed);
169		(*p1) as usize
170	}
171	pub fn set_value(addr: usize, value: &T) {
172		let con_addr = addr;
173		let p1 = unsafe { &*(&con_addr as *const usize as *mut Self) };
174		let mut lock = p1.value.value.lock().unwrap();
175		lock.0 = Some(value.clone());
176		let value_clone = p1.value.clone();
177		unsafe {
178			let au = addr as *mut AtomicUsize;
179			(*au).fetch_sub(1, Ordering::Relaxed);
180		}
181		if let Some(w) = lock.1.as_ref() {
182			w.wake_by_ref();
183		}
184		drop(value_clone);
185	}
186}