1use emscripten_val_sys::bind::*;
2use std::ffi::CString;
3
4use crate::utils::get_type_id;
5pub use emscripten_val_sys::bind::_embind_register_class_property;
6
7pub fn register_class<T: 'static>(name: &str) {
8 let type_id = get_type_id::<T>();
9 let ptr_type_id = get_type_id::<*mut T>();
10 let const_ptr_type_id = get_type_id::<*const T>();
11 let name_cstr = CString::new(name).unwrap();
12
13 extern "C" fn get_actual_type<T: 'static>(_ptr: *const ()) -> crate::TYPEID {
14 get_type_id::<T>()
15 }
16
17 extern "C" fn upcast(ptr: *const ()) -> *const () {
18 ptr
19 }
20
21 extern "C" fn downcast(ptr: *const ()) -> *const () {
22 ptr
23 }
24
25 extern "C" fn destructor<T>(ptr: *mut T) {
26 unsafe {
27 let _ = Box::from_raw(ptr);
28 }
29 }
30
31 unsafe {
32 _embind_register_class(
33 type_id,
34 ptr_type_id,
35 const_ptr_type_id,
36 std::ptr::null() as _, "pp\0".as_ptr() as _,
38 get_actual_type::<T> as _,
39 "pp\0".as_ptr() as _,
40 upcast as _,
41 "pp\0".as_ptr() as _,
42 downcast as _,
43 name_cstr.as_ptr(),
44 "vp\0".as_ptr() as _,
45 destructor::<T> as _,
46 );
47 }
48}
49
50pub fn register_class_default_constructor<T: 'static + Default>() {
51 extern "C" fn invoker<T: Default>(ptr: *const ()) -> *mut T {
52 let ptr: fn() -> T = unsafe { std::mem::transmute(ptr) };
53 let obj = Box::new(ptr());
54 Box::into_raw(obj) as _
55 }
56
57 unsafe {
58 let arg_types = [get_type_id::<*mut T>()];
59 _embind_register_class_constructor(
60 get_type_id::<T>(),
61 arg_types.len() as u32,
62 arg_types.as_ptr() as _,
63 "pp\0".as_ptr() as _,
64 invoker::<T> as _,
65 T::default as _,
66 )
67 }
68}
69
70#[macro_export]
71macro_rules! register_class_property {
72 ($cls:ty, $name:literal, $member:ident, $membertype:ty) => {{
73 let f = || unsafe {
74 extern "C" fn getter(_ctx: *mut (), ptr: *const $cls) -> $membertype {
75 unsafe { (*ptr).$member }
76 }
77
78 extern "C" fn setter(_ctx: *mut (), ptr: *mut $cls, value: $membertype) {
79 unsafe { (*ptr).$member = value; }
80 }
81
82 let cname = std::ffi::CString::new($name).unwrap();
83
84 let getter_signature = concat!(
85 stringify!(<$membertype>::signature()),
86 "pp\0"
87 );
88
89 let setter_signature = concat!(
90 "vpp",
91 stringify!(<$membertype>::signature()),
92 "\0"
93 );
94
95 _embind_register_class_property(
96 $crate::utils::get_type_id::<$cls>(),
97 cname.as_ptr(),
98 <$membertype>::id(),
99 getter_signature.as_ptr() as _,
100 getter as _,
101 std::ptr::null_mut(),
102 <$membertype>::id(),
103 setter_signature.as_ptr() as _,
104 setter as _,
105 std::ptr::null_mut(),
106 );
107 };
108 f();
109 }};
110}