1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::translate::*;
use crate::StaticType;
pub trait BoxedType: StaticType + Clone + Sized + 'static {
const NAME: &'static str;
}
pub fn register_boxed_type<T: BoxedType>() -> crate::Type {
unsafe extern "C" fn boxed_copy<T: BoxedType>(v: ffi::gpointer) -> ffi::gpointer {
let v = &*(v as *mut T);
let copy = Box::new(v.clone());
Box::into_raw(copy) as ffi::gpointer
}
unsafe extern "C" fn boxed_free<T: BoxedType>(v: ffi::gpointer) {
let v = v as *mut T;
let _ = Box::from_raw(v);
}
unsafe {
use std::ffi::CString;
let type_name = CString::new(T::NAME).unwrap();
if gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID {
panic!(
"Type {} has already been registered",
type_name.to_str().unwrap()
);
}
from_glib(gobject_ffi::g_boxed_type_register_static(
type_name.as_ptr(),
Some(boxed_copy::<T>),
Some(boxed_free::<T>),
))
}
}
#[cfg(test)]
mod test {
use crate as glib;
use crate::value::ToValue;
use crate::StaticType;
#[derive(Clone, Debug, PartialEq, Eq, glib::GBoxed)]
#[gboxed(type_name = "MyBoxed")]
struct MyBoxed(String);
#[test]
fn test_register() {
assert!(MyBoxed::static_type().is_valid());
}
#[test]
fn test_value() {
assert!(MyBoxed::static_type().is_valid());
let b = MyBoxed(String::from("abc"));
let v = b.to_value();
let b2 = v.get::<&MyBoxed>().unwrap();
assert_eq!(&b, b2);
}
}