@@ -55,22 +55,32 @@ pub use self::method::{
55
55
Method , MethodBuilder , RpcMode , ScriptMethod , ScriptMethodAttributes , ScriptMethodFn , Varargs ,
56
56
} ;
57
57
pub use self :: property:: { Export , ExportInfo , PropertyBuilder , Usage as PropertyUsage } ;
58
+ use std:: any:: TypeId ;
59
+ use std:: collections:: HashSet ;
60
+ use std:: sync:: Mutex ;
58
61
59
62
/// A handle that can register new classes to the engine during initialization.
60
63
///
61
64
/// See [`godot_nativescript_init`](macro.godot_nativescript_init.html) and
62
65
/// [`godot_init`](macro.godot_init.html).
63
66
#[ derive( Copy , Clone ) ]
64
- pub struct InitHandle {
67
+ pub struct InitHandle < ' a > {
65
68
#[ doc( hidden) ]
66
69
handle : * mut libc:: c_void ,
70
+ registered_classes : & ' a Mutex < HashSet < TypeId > > ,
67
71
}
68
72
69
- impl InitHandle {
73
+ impl < ' a > InitHandle < ' a > {
70
74
#[ doc( hidden) ]
71
75
#[ inline]
72
- pub unsafe fn new ( handle : * mut libc:: c_void ) -> Self {
73
- InitHandle { handle }
76
+ pub unsafe fn new (
77
+ handle : * mut libc:: c_void ,
78
+ registered_classes : & ' a Mutex < HashSet < TypeId > > ,
79
+ ) -> Self {
80
+ InitHandle {
81
+ handle,
82
+ registered_classes,
83
+ }
74
84
}
75
85
76
86
/// Registers a new class to the engine.
@@ -96,12 +106,20 @@ impl InitHandle {
96
106
where
97
107
C : NativeClassMethods ,
98
108
{
99
- if !class_registry:: register_class :: < C > ( ) {
109
+ if !self
110
+ . registered_classes
111
+ . lock ( )
112
+ . unwrap ( )
113
+ . insert ( TypeId :: of :: < C > ( ) )
114
+ {
100
115
panic ! (
101
- "`{type_name}` has already been registered" ,
116
+ "`{type_name}` has already been registered with this handle " ,
102
117
type_name = std:: any:: type_name:: <C >( )
103
118
) ;
104
119
}
120
+ if !class_registry:: register_class :: < C > ( ) {
121
+ // perhaps the library was kept alive while no NativeScripts referenced it
122
+ }
105
123
unsafe {
106
124
let class_name = CString :: new ( C :: class_name ( ) ) . unwrap ( ) ;
107
125
let base_name = CString :: new ( C :: Base :: class_name ( ) ) . unwrap ( ) ;
0 commit comments