Skip to content

Commit 5d4e1a6

Browse files
authored
Merge pull request #1436 from godot-rust/qol/uniform-ffi-rawptr
Unify raw pointer FFI passing with `RawPtr<P>` type
2 parents f67835d + 68b8a1f commit 5d4e1a6

File tree

22 files changed

+258
-200
lines changed

22 files changed

+258
-200
lines changed

godot-codegen/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ impl<'a> Context<'a> {
254254

255255
/// Yields cached sys pointer types – various pointer types declared in `gdextension_interface`
256256
/// and used as parameters in exposed Godot APIs.
257+
#[allow(dead_code)] // Currently unused, as RawPtr<P> covers all raw pointers.
257258
pub fn cached_sys_pointer_types(&self) -> impl Iterator<Item = &RustTy> {
258259
self.cached_rust_types
259260
.values()

godot-codegen/src/generator/central_files.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use quote::{format_ident, quote, ToTokens};
1010

1111
use crate::context::Context;
1212
use crate::conv;
13-
use crate::generator::sys_pointer_types::make_godotconvert_for_systypes;
1413
use crate::generator::{enums, gdext_build_struct};
1514
use crate::models::domain::{ExtensionApi, FlowDirection};
1615
use crate::util::ident;
@@ -61,7 +60,6 @@ pub fn make_core_central_code(api: &ExtensionApi, ctx: &mut Context) -> TokenStr
6160

6261
let (global_enum_defs, global_reexported_enum_defs) = make_global_enums(api);
6362
let variant_type_traits = make_variant_type_enum(api, false);
64-
let sys_types_godotconvert_impl = make_godotconvert_for_systypes(ctx);
6563

6664
// TODO impl Clone, Debug, PartialEq, PartialOrd, Hash for VariantDispatch
6765
// TODO could use try_to().unwrap_unchecked(), since type is already verified. Also directly overload from_variant().
@@ -119,15 +117,10 @@ pub fn make_core_central_code(api: &ExtensionApi, ctx: &mut Context) -> TokenStr
119117
#( #global_enum_defs )*
120118
}
121119

122-
pub mod global_reexported_enums {
120+
pub mod global_reexported_enums {
123121
use crate::sys;
124122
#( #global_reexported_enum_defs )*
125123
}
126-
127-
pub mod sys_pointer_types {
128-
use crate::sys;
129-
#( #sys_types_godotconvert_impl )*
130-
}
131124
}
132125
}
133126

godot-codegen/src/generator/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ pub mod method_tables;
2828
pub mod native_structures;
2929
pub mod notifications;
3030
pub mod signals;
31-
pub mod sys_pointer_types;
3231
pub mod utility_functions;
3332
pub mod virtual_definitions;
3433
pub mod virtual_traits;

godot-codegen/src/generator/native_structures.rs

Lines changed: 10 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ fn make_native_structure(
9393
let tokens = quote! {
9494
#imports
9595
use std::ffi::c_void; // for opaque object pointer fields
96-
use crate::meta::{GodotConvert, EngineFromGodot, EngineToGodot};
9796

9897
/// Native structure; can be passed via pointer in APIs that are not exposed to GDScript.
9998
///
@@ -107,58 +106,7 @@ fn make_native_structure(
107106
#methods
108107
}
109108

110-
impl GodotConvert for *mut #class_name {
111-
type Via = i64;
112-
}
113-
114-
// Native structure pointers implement internal-only conversion traits for use in engine APIs.
115-
impl EngineToGodot for *mut #class_name {
116-
type Pass = crate::meta::ByValue;
117-
118-
fn engine_to_godot(&self) -> crate::meta::ToArg<'_, Self::Via, Self::Pass> {
119-
*self as i64
120-
}
121-
122-
fn engine_to_variant(&self) -> crate::builtin::Variant {
123-
crate::builtin::Variant::from(*self as i64)
124-
}
125-
}
126-
127-
impl EngineFromGodot for *mut #class_name {
128-
fn engine_try_from_godot(via: Self::Via) -> Result<Self, crate::meta::error::ConvertError> {
129-
Ok(via as Self)
130-
}
131-
132-
fn engine_try_from_variant(variant: &crate::builtin::Variant) -> Result<Self, crate::meta::error::ConvertError> {
133-
variant.try_to::<i64>().map(|i| i as Self)
134-
}
135-
}
136-
137-
impl GodotConvert for *const #class_name {
138-
type Via = i64;
139-
}
140-
141-
impl EngineToGodot for *const #class_name {
142-
type Pass = crate::meta::ByValue;
143-
144-
fn engine_to_godot(&self) -> crate::meta::ToArg<'_, Self::Via, Self::Pass> {
145-
*self as i64
146-
}
147-
148-
fn engine_to_variant(&self) -> crate::builtin::Variant {
149-
crate::builtin::Variant::from(*self as i64)
150-
}
151-
}
152-
153-
impl EngineFromGodot for *const #class_name {
154-
fn engine_try_from_godot(via: Self::Via) -> Result<Self, crate::meta::error::ConvertError> {
155-
Ok(via as Self)
156-
}
157-
158-
fn engine_try_from_variant(variant: &crate::builtin::Variant) -> Result<Self, crate::meta::error::ConvertError> {
159-
variant.try_to::<i64>().map(|i| i as Self)
160-
}
161-
}
109+
// Pointer conversions are now handled by RawPtr<P>, no direct ToGodot/FromGodot impls.
162110
};
163111
// note: TypePtr -> ObjectPtr conversion OK?
164112

@@ -233,7 +181,11 @@ fn make_native_structure_field_and_accessor(
233181
}
234182

235183
/// Sets the object from a `Gd` pointer holding `Node` or a derived class.
236-
pub fn #setter_name<T>(&mut self, #snake_field_name: Gd<T>)
184+
///
185+
/// # Safety
186+
/// You must ensure that the provided object remains alive while Godot accesses it.
187+
/// See also [`RawPtr::new()`][crate::meta::RawPtr::new].
188+
pub unsafe fn #setter_name<T>(&mut self, #snake_field_name: Gd<T>)
237189
where T: crate::obj::Inherits<Object> {
238190
use crate::meta::GodotType as _;
239191

@@ -245,7 +197,10 @@ fn make_native_structure_field_and_accessor(
245197
let id = obj.instance_id().to_u64();
246198

247199
self.#id_field_name = ObjectId { id };
248-
self.#field_name = obj.obj_sys() as *mut std::ffi::c_void;
200+
201+
// SAFETY: provided by method safety contract.
202+
// Godot declares void* but expects GDExtensionObjectPtr.
203+
self.#field_name = unsafe { RawPtr::new(obj.obj_sys().cast::<std::ffi::c_void>()) };
249204
}
250205
});
251206
} else {

godot-codegen/src/generator/sys_pointer_types.rs

Lines changed: 0 additions & 37 deletions
This file was deleted.

godot-codegen/src/models/domain.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,11 +902,11 @@ impl ToTokens for RustTy {
902902
RustTy::RawPointer {
903903
inner,
904904
is_const: true,
905-
} => quote! { *const #inner }.to_tokens(tokens),
905+
} => quote! { crate::meta::RawPtr<*const #inner> }.to_tokens(tokens),
906906
RustTy::RawPointer {
907907
inner,
908908
is_const: false,
909-
} => quote! { *mut #inner }.to_tokens(tokens),
909+
} => quote! { crate::meta::RawPtr<*mut #inner> }.to_tokens(tokens),
910910
RustTy::EngineArray { tokens: path, .. } => path.to_tokens(tokens),
911911
RustTy::EngineEnum { tokens: path, .. } => path.to_tokens(tokens),
912912
RustTy::EngineClass {

godot-codegen/src/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn make_imports() -> TokenStream {
2525
quote! {
2626
use godot_ffi as sys;
2727
use crate::builtin::*;
28-
use crate::meta::{AsArg, ClassId, CowArg, InParamTuple, OutParamTuple, ParamTuple, RefArg, Signature};
28+
use crate::meta::{AsArg, ClassId, CowArg, InParamTuple, OutParamTuple, ParamTuple, RawPtr, RefArg, Signature};
2929
use crate::classes::native::*;
3030
use crate::classes::Object;
3131
use crate::obj::Gd;

godot-core/src/builtin/collections/any_array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl AnyArray {
6767
}
6868
}
6969

70-
/// Returns the value at the specified index.
70+
/// ⚠️ Returns the value at the specified index.
7171
///
7272
/// This replaces the `Index` trait, which cannot be implemented for `Array`, as it stores variants and not references.
7373
///

godot-core/src/builtin/collections/array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<T: ArrayElement> Array<T> {
255255
Self::default()
256256
}
257257

258-
/// Returns the value at the specified index.
258+
/// ⚠️ Returns the value at the specified index.
259259
///
260260
/// This replaces the `Index` trait, which cannot be implemented for `Array`, as it stores variants and not references.
261261
///
@@ -319,7 +319,7 @@ impl<T: ArrayElement> Array<T> {
319319
})
320320
}
321321

322-
/// Sets the value at the specified index.
322+
/// ⚠️ Sets the value at the specified index.
323323
///
324324
/// # Panics
325325
///

godot-core/src/builtin/collections/packed_array.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<T: PackedArrayElement> PackedArray<T> {
165165
// T::op_push_back(self.as_inner(), CowArg::Owned(value));
166166
// }
167167

168-
/// Inserts a new element at a given index in the array.
168+
/// ⚠️ Inserts a new element at a given index in the array.
169169
///
170170
/// The index must be valid, or at the end of the array (`index == len()`).
171171
///
@@ -180,7 +180,7 @@ impl<T: PackedArrayElement> PackedArray<T> {
180180
T::op_insert(self.as_inner(), to_i64(index), value.into_arg());
181181
}
182182

183-
/// Removes and returns the element at the specified index. Similar to `remove_at` in
183+
/// ⚠️ Removes and returns the element at the specified index. Similar to `remove_at` in
184184
/// GDScript, but also returns the removed value.
185185
///
186186
/// On large arrays, this method is much slower than `pop_back` as it will move all the array's

0 commit comments

Comments
 (0)