Skip to content

Commit 0ddbed9

Browse files
ttencatelilizoey
authored andcommitted
WIP: Implement #[func] for static functions
1 parent 0626d94 commit 0ddbed9

File tree

4 files changed

+117
-31
lines changed

4 files changed

+117
-31
lines changed

godot-core/src/builtin/meta/signature.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub trait SignatureTuple {
3131
args_ptr: *const sys::GDExtensionConstVariantPtr,
3232
ret: sys::GDExtensionVariantPtr,
3333
err: *mut sys::GDExtensionCallError,
34-
func: fn(&mut C, Self::Params) -> Self::Ret,
34+
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
3535
method_name: &str,
3636
);
3737

@@ -52,8 +52,7 @@ pub trait SignatureTuple {
5252
instance_ptr: sys::GDExtensionClassInstancePtr,
5353
args_ptr: *const sys::GDExtensionConstTypePtr,
5454
ret: sys::GDExtensionTypePtr,
55-
func: fn(&mut C, Self::Params) -> Self::Ret,
56-
method_name: &str,
55+
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
5756
call_type: sys::PtrcallType,
5857
);
5958
}
@@ -127,7 +126,7 @@ macro_rules! impl_signature_for_tuple {
127126

128127
#[inline]
129128
unsafe fn varcall<C : GodotClass>(
130-
instance_ptr: sys::GDExtensionClassInstancePtr,
129+
instance_ptr: sys::GDExtensionClassInstancePtr,
131130
args_ptr: *const sys::GDExtensionConstVariantPtr,
132131
ret: sys::GDExtensionVariantPtr,
133132
err: *mut sys::GDExtensionCallError,
@@ -163,13 +162,10 @@ macro_rules! impl_signature_for_tuple {
163162
args_ptr: *const sys::GDExtensionConstVariantPtr,
164163
ret: sys::GDExtensionVariantPtr,
165164
err: *mut sys::GDExtensionCallError,
166-
func: fn(&mut C, Self::Params) -> Self::Ret,
165+
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
167166
method_name: &str,
168167
) {
169-
$crate::out!("varcall: {}", method_name);
170-
171-
let storage = unsafe { crate::private::as_storage::<C>(instance_ptr) };
172-
let mut instance = storage.get_mut();
168+
$crate::out!("varcall: {}", method_name);
173169

174170
let args = ( $(
175171
{
@@ -181,17 +177,17 @@ macro_rules! impl_signature_for_tuple {
181177
},
182178
)* );
183179

184-
let ret_val = func(&mut *instance, args);
180+
let ret_val = func(instance_ptr, args);
185181
let ret_variant = <$R as ToVariant>::to_variant(&ret_val); // TODO write_sys
186-
unsafe {
182+
unsafe {
187183
*(ret as *mut Variant) = ret_variant;
188184
(*err).error = sys::GDEXTENSION_CALL_OK;
189185
}
190186
}
191187

192188
#[inline]
193189
unsafe fn ptrcall<C : GodotClass>(
194-
instance_ptr: sys::GDExtensionClassInstancePtr,
190+
instance_ptr: sys::GDExtensionClassInstancePtr,
195191
args_ptr: *const sys::GDExtensionConstTypePtr,
196192
ret: sys::GDExtensionTypePtr,
197193
func: fn(&C, Self::Params) -> Self::Ret,
@@ -226,16 +222,12 @@ macro_rules! impl_signature_for_tuple {
226222
instance_ptr: sys::GDExtensionClassInstancePtr,
227223
args_ptr: *const sys::GDExtensionConstTypePtr,
228224
ret: sys::GDExtensionTypePtr,
229-
func: fn(&mut C, Self::Params) -> Self::Ret,
230-
method_name: &str,
225+
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
231226
call_type: sys::PtrcallType,
232227
) {
233228
$crate::out!("ptrcall: {}", method_name);
234229

235-
let storage = unsafe { crate::private::as_storage::<C>(instance_ptr) };
236-
let mut instance = storage.get_mut();
237-
238-
let args = ( $(
230+
let args = ( $(
239231
unsafe {
240232
<$Pn as sys::GodotFuncMarshal>::try_from_arg(
241233
sys::force_mut_ptr(*args_ptr.offset($n)),
@@ -245,7 +237,7 @@ macro_rules! impl_signature_for_tuple {
245237
.unwrap_or_else(|e| param_error::<$Pn>(method_name, $n, &e)),
246238
)* );
247239

248-
let ret_val = func(&mut *instance, args);
240+
let ret_val = func(instance_ptr, args);
249241
// SAFETY:
250242
// `ret` is always a pointer to an initialized value of type $R
251243
// TODO: double-check the above

godot-core/src/macros.rs

Lines changed: 88 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,54 @@ macro_rules! gdext_is_not_unit {
3737
};
3838
}
3939

40+
#[doc(hidden)]
41+
#[macro_export]
42+
macro_rules! gdext_method_flags {
43+
(INSTANCE) => {
44+
$crate::sys::GDEXTENSION_METHOD_FLAGS_DEFAULT
45+
};
46+
(STATIC) => {
47+
$crate::sys::GDEXTENSION_METHOD_FLAG_STATIC
48+
};
49+
}
50+
51+
#[doc(hidden)]
52+
#[macro_export]
53+
macro_rules! gdext_wrap_with_unpacked_params {
54+
(
55+
INSTANCE,
56+
$Class:ty,
57+
$method_name:ident,
58+
$( $param:ident, )*
59+
) => {
60+
|instance_ptr, params| {
61+
let storage = unsafe { $crate::private::as_storage::<$Class>(instance_ptr) };
62+
let mut instance = storage.get_mut();
63+
let ( $($param,)* ) = params;
64+
instance.$method_name( $( $param, )* )
65+
}
66+
};
67+
(
68+
STATIC,
69+
$Class:ty,
70+
$method_name:ident,
71+
$( $param:ident, )*
72+
) => {
73+
|instance_ptr, params| {
74+
let ( $($param,)* ) = params;
75+
<$Class>::$method_name( $( $param, )* )
76+
}
77+
};
78+
}
79+
4080
#[doc(hidden)]
4181
#[macro_export]
4282
macro_rules! gdext_register_method_inner {
4383
(
4484
$ptrcall:ident,
4585
$varcall:ident,
86+
$instance_or_static:ident, // "INSTANCE" or "STATIC"
4687
$Class:ty,
47-
$map_method:ident,
4888
fn $method_name:ident(
4989
$( $param:ident : $ParamTy:ty, )*
5090
$( #[opt] $opt_param:ident : $OptParamTy:ty, )*
@@ -76,10 +116,8 @@ macro_rules! gdext_register_method_inner {
76116
args,
77117
ret,
78118
err,
79-
|inst, params| {
80-
let ( $($param,)* ) = params;
81-
inst.$method_name( $( $param, )* )
82-
},
119+
$crate::gdext_wrap_with_unpacked_params!(
120+
$instance_or_static, $Class, $method_name, $($param,)*),
83121
stringify!($method_name),
84122
);
85123
}
@@ -109,10 +147,8 @@ macro_rules! gdext_register_method_inner {
109147
instance_ptr,
110148
args,
111149
ret,
112-
|inst, params| {
113-
let ( $($param,)* ) = params;
114-
inst.$method_name( $( $param, )* )
115-
},
150+
$crate::gdext_wrap_with_unpacked_params!(
151+
$instance_or_static, $Class, $method_name, $($param,)*),
116152
stringify!($method_name),
117153
sys::PtrcallType::Standard
118154
);
@@ -163,7 +199,7 @@ macro_rules! gdext_register_method_inner {
163199
method_userdata: std::ptr::null_mut(),
164200
call_func: Some(varcall_func),
165201
ptrcall_func: Some(ptrcall_func),
166-
method_flags: sys::GDEXTENSION_METHOD_FLAGS_DEFAULT as u32,
202+
method_flags: $crate::gdext_method_flags!($instance_or_static) as u32,
167203
has_return_value: has_return_value as u8,
168204
return_value_info: std::ptr::addr_of_mut!(return_value_info_sys),
169205
return_value_metadata,
@@ -207,8 +243,8 @@ macro_rules! gdext_register_method {
207243
$crate::gdext_register_method_inner!(
208244
ptrcall_mut,
209245
varcall_mut,
246+
INSTANCE,
210247
$Class,
211-
map_mut,
212248
fn $method_name(
213249
$( $param : $ParamTy, )*
214250
$( #[opt] $opt_param : $OptParamTy, )*
@@ -229,8 +265,29 @@ macro_rules! gdext_register_method {
229265
$crate::gdext_register_method_inner!(
230266
ptrcall,
231267
varcall,
268+
INSTANCE,
269+
$Class,
270+
fn $method_name(
271+
$( $arg : $Param, )*
272+
$( #[opt] $opt_arg : $OptParam, )*
273+
) -> $RetTy
274+
)
275+
};
276+
277+
// static
278+
(
279+
$Class:ty,
280+
fn $method_name:ident(
281+
$( $arg:ident : $Param:ty),*
282+
$(, #[opt] $opt_arg:ident : $OptParam:ty)*
283+
$(,)?
284+
) -> $RetTy:ty
285+
) => {
286+
$crate::gdext_register_method_inner!(
287+
ptrcall_mut,
288+
varcall_mut,
289+
STATIC,
232290
$Class,
233-
map,
234291
fn $method_name(
235292
$( $arg : $Param, )*
236293
$( #[opt] $opt_arg : $OptParam, )*
@@ -279,6 +336,25 @@ macro_rules! gdext_register_method {
279336
) -> ()
280337
)
281338
};
339+
340+
// static without return type
341+
(
342+
$Class:ty,
343+
fn $method_name:ident(
344+
$( $param:ident : $ParamTy:ty ),*
345+
$(, #[opt] $opt_param:ident : $OptParamTy:ty )*
346+
$(,)?
347+
)
348+
) => {
349+
// recurse this macro
350+
$crate::gdext_register_method!(
351+
$Class,
352+
fn $method_name(
353+
$( $param : $ParamTy, )*
354+
$( #[opt] $opt_param : $OptParamTy, )*
355+
) -> ()
356+
)
357+
};
282358
}
283359

284360
#[doc(hidden)]

itest/godot/ManualFfiTests.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ func test_init_defaults():
2525
assert_eq(obj.literal_int, 42)
2626
assert_eq(obj.expr_int, -42)
2727

28+
func test_static():
29+
assert_eq(StaticMethods.return_int(), 42)
30+
assert_eq(StaticMethods.add(2, 2), 4)
31+
2832
func test_to_string():
2933
var ffi = VirtualMethodTest.new()
3034

itest/rust/src/object_test.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,17 @@ fn double_use_reference() {
826826
double_use.free();
827827
emitter.free();
828828
}
829+
struct StaticMethods {}
830+
831+
#[godot_api]
832+
impl StaticMethods {
833+
#[func]
834+
fn return_int() -> i64 {
835+
42
836+
}
837+
838+
#[func]
839+
fn add(a: i64, b: i64) -> i64 {
840+
a + b
841+
}
842+
}

0 commit comments

Comments
 (0)