@@ -35,6 +35,14 @@ pub trait SignatureTuple {
35
35
method_name : & str ,
36
36
) ;
37
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 ,
43
+ method_name : & str ,
44
+ ) ;
45
+
38
46
// Note: this method imposes extra bounds on GodotFfi, which may not be implemented for user types.
39
47
// We could fall back to varcalls in such cases, and not require GodotFfi categorically.
40
48
unsafe fn ptrcall < C : GodotClass > (
@@ -56,6 +64,16 @@ pub trait SignatureTuple {
56
64
method_name : & str ,
57
65
call_type : sys:: PtrcallType ,
58
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 ,
75
+ call_type : sys:: PtrcallType ,
76
+ ) ;
59
77
}
60
78
61
79
// impl<P, const N: usize> Sig for [P; N]
@@ -127,71 +145,72 @@ macro_rules! impl_signature_for_tuple {
127
145
128
146
#[ inline]
129
147
unsafe fn varcall<C : GodotClass >(
130
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
148
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
131
149
args_ptr: * const sys:: GDExtensionConstVariantPtr ,
132
150
ret: sys:: GDExtensionVariantPtr ,
133
151
err: * mut sys:: GDExtensionCallError ,
134
152
func: fn ( & C , Self :: Params ) -> Self :: Ret ,
135
153
method_name: & str ,
136
154
) {
137
- $crate:: out!( "varcall: {}" , method_name) ;
155
+ $crate:: out!( "varcall: {}" , method_name) ;
138
156
139
157
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
140
158
let instance = storage. get( ) ;
141
159
142
- let args = ( $(
143
- {
144
- let variant = unsafe { & * ( * args_ptr. offset( $n) as * mut Variant ) } ; // TODO from_var_sys
145
- let arg = <$Pn as FromVariant >:: try_from_variant( variant)
146
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, variant) ) ;
147
-
148
- arg
149
- } ,
150
- ) * ) ;
151
-
152
- let ret_val = func( & * instance, args) ;
153
- let ret_variant = <$R as ToVariant >:: to_variant( & ret_val) ; // TODO write_sys
154
- unsafe {
155
- * ( ret as * mut Variant ) = ret_variant;
156
- ( * err) . error = sys:: GDEXTENSION_CALL_OK ;
157
- }
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)
158
167
}
159
168
160
169
#[ inline]
161
170
unsafe fn varcall_mut<C : GodotClass >(
162
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
171
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
163
172
args_ptr: * const sys:: GDExtensionConstVariantPtr ,
164
173
ret: sys:: GDExtensionVariantPtr ,
165
174
err: * mut sys:: GDExtensionCallError ,
166
175
func: fn ( & mut C , Self :: Params ) -> Self :: Ret ,
167
176
method_name: & str ,
168
177
) {
169
- $crate:: out!( "varcall : {}" , method_name) ;
178
+ $crate:: out!( "varcall_mut : {}" , method_name) ;
170
179
171
180
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
172
181
let mut instance = storage. get_mut( ) ;
173
182
174
- let args = ( $(
175
- {
176
- let variant = unsafe { & * ( * args_ptr. offset( $n) as * mut Variant ) } ; // TODO from_var_sys
177
- let arg = <$Pn as FromVariant >:: try_from_variant( variant)
178
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, variant) ) ;
179
-
180
- arg
181
- } ,
182
- ) * ) ;
183
-
184
- let ret_val = func( & mut * instance, args) ;
185
- let ret_variant = <$R as ToVariant >:: to_variant( & ret_val) ; // TODO write_sys
186
- unsafe {
187
- * ( ret as * mut Variant ) = ret_variant;
188
- ( * err) . error = sys:: GDEXTENSION_CALL_OK ;
189
- }
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)
190
209
}
191
210
192
211
#[ inline]
193
212
unsafe fn ptrcall<C : GodotClass >(
194
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
213
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
195
214
args_ptr: * const sys:: GDExtensionConstTypePtr ,
196
215
ret: sys:: GDExtensionTypePtr ,
197
216
func: fn ( & C , Self :: Params ) -> Self :: Ret ,
@@ -203,59 +222,117 @@ macro_rules! impl_signature_for_tuple {
203
222
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
204
223
let instance = storage. get( ) ;
205
224
206
- let args = ( $(
207
- unsafe {
208
- <$Pn as sys:: GodotFuncMarshal >:: try_from_arg(
209
- sys:: force_mut_ptr( * args_ptr. offset( $n) ) ,
210
- call_type
211
- )
212
- }
213
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, & e) ) ,
214
- ) * ) ;
215
-
216
- let ret_val = func( & * instance, args) ;
225
+ let args = ( $( unsafe { ptrcall_arg:: <$Pn, $n>( args_ptr, method_name, call_type) } , ) * ) ;
226
+
217
227
// SAFETY:
218
228
// `ret` is always a pointer to an initialized value of type $R
219
229
// TODO: double-check the above
220
- <$R as sys:: GodotFuncMarshal >:: try_return( ret_val, ret, call_type)
221
- . unwrap_or_else( |ret_val| return_error:: <$R>( method_name, & ret_val) ) ;
230
+ ptrcall_return:: <$R>( func( & * instance, args) , ret, method_name, call_type)
222
231
}
223
232
224
233
#[ inline]
225
234
unsafe fn ptrcall_mut<C : GodotClass >(
226
- instance_ptr: sys:: GDExtensionClassInstancePtr ,
235
+ instance_ptr: sys:: GDExtensionClassInstancePtr ,
227
236
args_ptr: * const sys:: GDExtensionConstTypePtr ,
228
237
ret: sys:: GDExtensionTypePtr ,
229
238
func: fn ( & mut C , Self :: Params ) -> Self :: Ret ,
230
239
method_name: & str ,
231
240
call_type: sys:: PtrcallType ,
232
241
) {
233
- $crate:: out!( "ptrcall : {}" , method_name) ;
242
+ $crate:: out!( "ptrcall_mut : {}" , method_name) ;
234
243
235
244
let storage = unsafe { crate :: private:: as_storage:: <C >( instance_ptr) } ;
236
245
let mut instance = storage. get_mut( ) ;
237
246
238
- let args = ( $(
239
- unsafe {
240
- <$Pn as sys:: GodotFuncMarshal >:: try_from_arg(
241
- sys:: force_mut_ptr( * args_ptr. offset( $n) ) ,
242
- call_type
243
- )
244
- }
245
- . unwrap_or_else( |e| param_error:: <$Pn>( method_name, $n, & e) ) ,
246
- ) * ) ;
247
-
248
- let ret_val = func( & mut * instance, args) ;
247
+ let args = ( $( unsafe { ptrcall_arg:: <$Pn, $n>( args_ptr, method_name, call_type) } , ) * ) ;
248
+
249
249
// SAFETY:
250
250
// `ret` is always a pointer to an initialized value of type $R
251
251
// TODO: double-check the above
252
- <$R as sys:: GodotFuncMarshal >:: try_return( ret_val, ret, call_type)
253
- . unwrap_or_else( |ret_val| return_error:: <$R>( method_name, & ret_val) ) ;
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) } , ) * ) ;
266
+
267
+ // SAFETY:
268
+ // `ret` is always a pointer to an initialized value of type $R
269
+ // TODO: double-check the above
270
+ ptrcall_return:: <$R>( func( args) , ret, method_name, call_type)
254
271
}
255
272
}
256
273
} ;
257
274
}
258
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
+
259
336
fn param_error < P > ( method_name : & str , index : i32 , arg : & impl Debug ) -> ! {
260
337
let param_ty = std:: any:: type_name :: < P > ( ) ;
261
338
panic ! (
0 commit comments