@@ -31,7 +31,15 @@ pub trait SignatureTuple {
31
31
args_ptr : * const sys:: GDExtensionConstVariantPtr ,
32
32
ret : sys:: GDExtensionVariantPtr ,
33
33
err : * mut sys:: GDExtensionCallError ,
34
- func : fn ( sys:: GDExtensionClassInstancePtr , Self :: Params ) -> Self :: Ret ,
34
+ func : fn ( & mut C , Self :: Params ) -> Self :: Ret ,
35
+ method_name : & str ,
36
+ ) ;
37
+
38
+ unsafe fn varcall_static < C : GodotClass > (
39
+ args_ptr : * const sys:: GDExtensionConstVariantPtr ,
40
+ ret : sys:: GDExtensionVariantPtr ,
41
+ err : * mut sys:: GDExtensionCallError ,
42
+ func : fn ( Self :: Params ) -> Self :: Ret ,
35
43
method_name : & str ,
36
44
) ;
37
45
@@ -52,7 +60,18 @@ pub trait SignatureTuple {
52
60
instance_ptr : sys:: GDExtensionClassInstancePtr ,
53
61
args_ptr : * const sys:: GDExtensionConstTypePtr ,
54
62
ret : sys:: GDExtensionTypePtr ,
55
- func : fn ( sys:: GDExtensionClassInstancePtr , Self :: Params ) -> Self :: Ret ,
63
+ func : fn ( & mut C , Self :: Params ) -> Self :: Ret ,
64
+ method_name : & str ,
65
+ call_type : sys:: PtrcallType ,
66
+ ) ;
67
+
68
+ // Note: this method imposes extra bounds on GodotFfi, which may not be implemented for user types.
69
+ // We could fall back to varcalls in such cases, and not require GodotFfi categorically.
70
+ unsafe fn ptrcall_static < C : GodotClass > (
71
+ args_ptr : * const sys:: GDExtensionConstTypePtr ,
72
+ ret : sys:: GDExtensionTypePtr ,
73
+ func : fn ( Self :: Params ) -> Self :: Ret ,
74
+ method_name : & str ,
56
75
call_type : sys:: PtrcallType ,
57
76
) ;
58
77
}
@@ -133,56 +152,60 @@ macro_rules! impl_signature_for_tuple {
133
152
func: fn ( & C , Self :: Params ) -> Self :: Ret ,
134
153
method_name: & str ,
135
154
) {
136
- $crate:: out!( "varcall: {}" , method_name) ;
155
+ $crate:: out!( "varcall: {}" , method_name) ;
137
156
138
157
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
139
158
let instance = storage. get( ) ;
140
159
141
- let args = ( $(
142
- {
143
- let variant = unsafe { & * ( * args_ptr. offset( $n) as * mut Variant ) } ; // TODO from_var_sys
144
- let arg = <$Pn as FromVariant >:: try_from_variant( variant)
145
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, variant) ) ;
146
-
147
- arg
148
- } ,
149
- ) * ) ;
150
-
151
- let ret_val = func( & * instance, args) ;
152
- let ret_variant = <$R as ToVariant >:: to_variant( & ret_val) ; // TODO write_sys
153
- unsafe {
154
- * ( ret as * mut Variant ) = ret_variant;
155
- ( * err) . error = sys:: GDEXTENSION_CALL_OK ;
156
- }
160
+ let args_ptr = args_ptr as * const * mut Variant ;
161
+
162
+ let args = ( $( unsafe { varcall_arg:: <$Pn, $n>( args_ptr, method_name) } , ) * ) ;
163
+
164
+ let ret = ret as * mut Variant ;
165
+
166
+ varcall_return:: <$R>( func( & * instance, args) , ret, err)
157
167
}
158
168
159
169
#[ inline]
160
170
unsafe fn varcall_mut<C : GodotClass >(
161
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
171
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
162
172
args_ptr: * const sys:: GDExtensionConstVariantPtr ,
163
173
ret: sys:: GDExtensionVariantPtr ,
164
174
err: * mut sys:: GDExtensionCallError ,
165
- func: fn ( sys :: GDExtensionClassInstancePtr , Self :: Params ) -> Self :: Ret ,
175
+ func: fn ( & mut C , Self :: Params ) -> Self :: Ret ,
166
176
method_name: & str ,
167
177
) {
168
- $crate:: out!( "varcall : {}" , method_name) ;
178
+ $crate:: out!( "varcall_mut : {}" , method_name) ;
169
179
170
- let args = ( $(
171
- {
172
- let variant = unsafe { & * ( * args_ptr. offset( $n) as * mut Variant ) } ; // TODO from_var_sys
173
- let arg = <$Pn as FromVariant >:: try_from_variant( variant)
174
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, variant) ) ;
175
-
176
- arg
177
- } ,
178
- ) * ) ;
179
-
180
- let ret_val = func( instance_ptr, args) ;
181
- let ret_variant = <$R as ToVariant >:: to_variant( & ret_val) ; // TODO write_sys
182
- unsafe {
183
- * ( ret as * mut Variant ) = ret_variant;
184
- ( * err) . error = sys:: GDEXTENSION_CALL_OK ;
185
- }
180
+ let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
181
+ let mut instance = storage. get_mut( ) ;
182
+
183
+ let args_ptr = args_ptr as * const * mut Variant ;
184
+
185
+ let args = ( $( unsafe { varcall_arg:: <$Pn, $n>( args_ptr, method_name) } , ) * ) ;
186
+
187
+ let ret = ret as * mut Variant ;
188
+
189
+ varcall_return:: <$R>( func( & mut * instance, args) , ret, err)
190
+ }
191
+
192
+ #[ inline]
193
+ unsafe fn varcall_static<C : GodotClass >(
194
+ args_ptr: * const sys:: GDExtensionConstVariantPtr ,
195
+ ret: sys:: GDExtensionVariantPtr ,
196
+ err: * mut sys:: GDExtensionCallError ,
197
+ func: fn ( Self :: Params ) -> Self :: Ret ,
198
+ method_name: & str ,
199
+ ) {
200
+ $crate:: out!( "varcall_static: {}" , method_name) ;
201
+
202
+ let args_ptr = args_ptr as * const * mut Variant ;
203
+
204
+ let args = ( $( unsafe { varcall_arg:: <$Pn, $n>( args_ptr, method_name) } , ) * ) ;
205
+
206
+ let ret = ret as * mut Variant ;
207
+
208
+ varcall_return:: <$R>( func( args) , ret, err)
186
209
}
187
210
188
211
#[ inline]
@@ -199,55 +222,117 @@ macro_rules! impl_signature_for_tuple {
199
222
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
200
223
let instance = storage. get( ) ;
201
224
202
- let args = ( $(
203
- unsafe {
204
- <$Pn as sys:: GodotFuncMarshal >:: try_from_arg(
205
- sys:: force_mut_ptr( * args_ptr. offset( $n) ) ,
206
- call_type
207
- )
208
- }
209
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, & e) ) ,
210
- ) * ) ;
211
-
212
- let ret_val = func( & * instance, args) ;
225
+ let args = ( $( unsafe { ptrcall_arg:: <$Pn, $n>( args_ptr, method_name, call_type) } , ) * ) ;
226
+
213
227
// SAFETY:
214
228
// `ret` is always a pointer to an initialized value of type $R
215
229
// TODO: double-check the above
216
- <$R as sys:: GodotFuncMarshal >:: try_return( ret_val, ret, call_type)
217
- . unwrap_or_else( |ret_val| return_error:: <$R>( method_name, & ret_val) ) ;
230
+ ptrcall_return:: <$R>( func( & * instance, args) , ret, method_name, call_type)
218
231
}
219
232
220
233
#[ inline]
221
234
unsafe fn ptrcall_mut<C : GodotClass >(
222
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
235
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
223
236
args_ptr: * const sys:: GDExtensionConstTypePtr ,
224
237
ret: sys:: GDExtensionTypePtr ,
225
- func: fn ( sys:: GDExtensionClassInstancePtr , Self :: Params ) -> Self :: Ret ,
238
+ func: fn ( & mut C , Self :: Params ) -> Self :: Ret ,
239
+ method_name: & str ,
226
240
call_type: sys:: PtrcallType ,
227
241
) {
228
- $crate:: out!( "ptrcall: {}" , method_name) ;
242
+ $crate:: out!( "ptrcall_mut: {}" , method_name) ;
243
+
244
+ let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
245
+ let mut instance = storage. get_mut( ) ;
246
+
247
+ let args = ( $( unsafe { ptrcall_arg:: <$Pn, $n>( args_ptr, method_name, call_type) } , ) * ) ;
248
+
249
+ // SAFETY:
250
+ // `ret` is always a pointer to an initialized value of type $R
251
+ // TODO: double-check the above
252
+ ptrcall_return:: <$R>( func( & mut * instance, args) , ret, method_name, call_type)
253
+ }
254
+
255
+ #[ inline]
256
+ unsafe fn ptrcall_static<C : GodotClass >(
257
+ args_ptr: * const sys:: GDExtensionConstTypePtr ,
258
+ ret: sys:: GDExtensionTypePtr ,
259
+ func: fn ( Self :: Params ) -> Self :: Ret ,
260
+ method_name: & str ,
261
+ call_type: sys:: PtrcallType ,
262
+ ) {
263
+ $crate:: out!( "ptrcall_static: {}" , method_name) ;
264
+
265
+ let args = ( $( unsafe { ptrcall_arg:: <$Pn, $n>( args_ptr, method_name, call_type) } , ) * ) ;
229
266
230
- let args = ( $(
231
- unsafe {
232
- <$Pn as sys:: GodotFuncMarshal >:: try_from_arg(
233
- sys:: force_mut_ptr( * args_ptr. offset( $n) ) ,
234
- call_type
235
- )
236
- }
237
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, & e) ) ,
238
- ) * ) ;
239
-
240
- let ret_val = func( instance_ptr, args) ;
241
267
// SAFETY:
242
268
// `ret` is always a pointer to an initialized value of type $R
243
269
// TODO: double-check the above
244
- <$R as sys:: GodotFuncMarshal >:: try_return( ret_val, ret, call_type)
245
- . unwrap_or_else( |ret_val| return_error:: <$R>( method_name, & ret_val) ) ;
270
+ ptrcall_return:: <$R>( func( args) , ret, method_name, call_type)
246
271
}
247
272
}
248
273
} ;
249
274
}
250
275
276
+ /// Convert the `N`th argument of `args_ptr` into a value of type `P`.
277
+ ///
278
+ /// # Safety
279
+ /// - It must be safe to dereference the pointer at `args_ptr.offset(N)` .
280
+ unsafe fn varcall_arg < P : FromVariant , const N : isize > (
281
+ args_ptr : * const * mut Variant ,
282
+ method_name : & str ,
283
+ ) -> P {
284
+ let variant = & * ( * args_ptr. offset ( N ) ) ; // TODO from_var_sys
285
+ P :: try_from_variant ( variant)
286
+ . unwrap_or_else ( |_| param_error :: < P > ( method_name, N as i32 , variant) )
287
+ }
288
+
289
+ /// Moves `ret_val` into `ret`.
290
+ ///
291
+ /// # Safety
292
+ /// - `ret` must be a pointer to an initialized `Variant`.
293
+ /// - It must be safe to write a `Variant` once to `ret`.
294
+ /// - It must be safe to write a `sys::GDExtensionCallError` once to `err`.
295
+ unsafe fn varcall_return < R : ToVariant > (
296
+ ret_val : R ,
297
+ ret : * mut Variant ,
298
+ err : * mut sys:: GDExtensionCallError ,
299
+ ) {
300
+ let ret_variant = ret_val. to_variant ( ) ; // TODO write_sys
301
+ * ret = ret_variant;
302
+ ( * err) . error = sys:: GDEXTENSION_CALL_OK ;
303
+ }
304
+
305
+ /// Convert the `N`th argument of `args_ptr` into a value of type `P`.
306
+ ///
307
+ /// # Safety
308
+ /// - It must be safe to dereference the address at `args_ptr.offset(N)` .
309
+ /// - The pointer at `args_ptr.offset(N)` must follow the safety requirements as laid out in
310
+ /// [`GodotFuncMarshal::try_from_arg`][sys::GodotFuncMarshal::try_from_arg].
311
+ unsafe fn ptrcall_arg < P : sys:: GodotFuncMarshal , const N : isize > (
312
+ args_ptr : * const sys:: GDExtensionConstTypePtr ,
313
+ method_name : & str ,
314
+ call_type : sys:: PtrcallType ,
315
+ ) -> P {
316
+ P :: try_from_arg ( sys:: force_mut_ptr ( * args_ptr. offset ( N ) ) , call_type)
317
+ . unwrap_or_else ( |e| param_error :: < P > ( method_name, N as i32 , & e) )
318
+ }
319
+
320
+ /// Moves `ret_val` into `ret`.
321
+ ///
322
+ /// # Safety
323
+ /// `ret_val`, `ret`, and `call_type` must follow the safety requirements as laid out in
324
+ /// [`GodotFuncMarshal::try_return`](sys::GodotFuncMarshal::try_return).
325
+ unsafe fn ptrcall_return < R : sys:: GodotFuncMarshal + std:: fmt:: Debug > (
326
+ ret_val : R ,
327
+ ret : sys:: GDExtensionTypePtr ,
328
+ method_name : & str ,
329
+ call_type : sys:: PtrcallType ,
330
+ ) {
331
+ ret_val
332
+ . try_return ( ret, call_type)
333
+ . unwrap_or_else ( |ret_val| return_error :: < R > ( method_name, & ret_val) )
334
+ }
335
+
251
336
fn param_error < P > ( method_name : & str , index : i32 , arg : & impl Debug ) -> ! {
252
337
let param_ty = std:: any:: type_name :: < P > ( ) ;
253
338
panic ! (
0 commit comments