generator: Turn c_void-returning functions into Rust () (#362)
`c_void` is not the same as Rust's void type, `()`, making function pointers like `PFN_vkFreeFunction` pretty much impossible to implement without casting. Instead of just turning this into `-> ()`, remove the return type altogether, and add some asserts to prevent types of this kind from being accidentally generated.
This commit is contained in:
parent
dd2849450f
commit
e8b369db7d
|
@ -383,7 +383,7 @@ pub type PFN_vkInternalAllocationNotification = Option<
|
||||||
size: usize,
|
size: usize,
|
||||||
allocation_type: InternalAllocationType,
|
allocation_type: InternalAllocationType,
|
||||||
allocation_scope: SystemAllocationScope,
|
allocation_scope: SystemAllocationScope,
|
||||||
) -> c_void,
|
),
|
||||||
>;
|
>;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkInternalFreeNotification.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkInternalFreeNotification.html>"]
|
||||||
|
@ -393,7 +393,7 @@ pub type PFN_vkInternalFreeNotification = Option<
|
||||||
size: usize,
|
size: usize,
|
||||||
allocation_type: InternalAllocationType,
|
allocation_type: InternalAllocationType,
|
||||||
allocation_scope: SystemAllocationScope,
|
allocation_scope: SystemAllocationScope,
|
||||||
) -> c_void,
|
),
|
||||||
>;
|
>;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkReallocationFunction.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkReallocationFunction.html>"]
|
||||||
|
@ -419,10 +419,10 @@ pub type PFN_vkAllocationFunction = Option<
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkFreeFunction.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkFreeFunction.html>"]
|
||||||
pub type PFN_vkFreeFunction =
|
pub type PFN_vkFreeFunction =
|
||||||
Option<unsafe extern "system" fn(p_user_data: *mut c_void, p_memory: *mut c_void) -> c_void>;
|
Option<unsafe extern "system" fn(p_user_data: *mut c_void, p_memory: *mut c_void)>;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkVoidFunction.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkVoidFunction.html>"]
|
||||||
pub type PFN_vkVoidFunction = Option<unsafe extern "system" fn() -> c_void>;
|
pub type PFN_vkVoidFunction = Option<unsafe extern "system" fn()>;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkDebugReportCallbackEXT.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/PFN_vkDebugReportCallbackEXT.html>"]
|
||||||
pub type PFN_vkDebugReportCallbackEXT = Option<
|
pub type PFN_vkDebugReportCallbackEXT = Option<
|
||||||
|
@ -453,7 +453,7 @@ pub type PFN_vkDeviceMemoryReportCallbackEXT = Option<
|
||||||
unsafe extern "system" fn(
|
unsafe extern "system" fn(
|
||||||
p_callback_data: *const DeviceMemoryReportCallbackDataEXT,
|
p_callback_data: *const DeviceMemoryReportCallbackDataEXT,
|
||||||
p_user_data: *mut c_void,
|
p_user_data: *mut c_void,
|
||||||
) -> c_void,
|
),
|
||||||
>;
|
>;
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -623,6 +623,9 @@ pub trait FieldExt {
|
||||||
/// which is needed for `C` function parameters. Set to `false` for struct definitions.
|
/// which is needed for `C` function parameters. Set to `false` for struct definitions.
|
||||||
fn type_tokens(&self, is_ffi_param: bool) -> TokenStream;
|
fn type_tokens(&self, is_ffi_param: bool) -> TokenStream;
|
||||||
fn is_clone(&self) -> bool;
|
fn is_clone(&self) -> bool;
|
||||||
|
|
||||||
|
/// Whether this is C's `void` type (not to be mistaken with a void _pointer_!)
|
||||||
|
fn is_void(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToTokens {
|
pub trait ToTokens {
|
||||||
|
@ -729,6 +732,7 @@ impl FieldExt for vkxml::Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner_type_tokens(&self) -> TokenStream {
|
fn inner_type_tokens(&self) -> TokenStream {
|
||||||
|
assert!(!self.is_void());
|
||||||
let ty = name_to_tokens(&self.basetype);
|
let ty = name_to_tokens(&self.basetype);
|
||||||
|
|
||||||
match self.reference {
|
match self.reference {
|
||||||
|
@ -739,6 +743,7 @@ impl FieldExt for vkxml::Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn safe_type_tokens(&self, lifetime: TokenStream) -> TokenStream {
|
fn safe_type_tokens(&self, lifetime: TokenStream) -> TokenStream {
|
||||||
|
assert!(!self.is_void());
|
||||||
match self.array {
|
match self.array {
|
||||||
// The outer type fn type_tokens() returns is [], which fits our "safe" prescription
|
// The outer type fn type_tokens() returns is [], which fits our "safe" prescription
|
||||||
Some(vkxml::ArrayType::Static) => self.type_tokens(false),
|
Some(vkxml::ArrayType::Static) => self.type_tokens(false),
|
||||||
|
@ -758,6 +763,7 @@ impl FieldExt for vkxml::Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_tokens(&self, is_ffi_param: bool) -> TokenStream {
|
fn type_tokens(&self, is_ffi_param: bool) -> TokenStream {
|
||||||
|
assert!(!self.is_void());
|
||||||
let ty = name_to_tokens(&self.basetype);
|
let ty = name_to_tokens(&self.basetype);
|
||||||
|
|
||||||
match self.array {
|
match self.array {
|
||||||
|
@ -784,6 +790,10 @@ impl FieldExt for vkxml::Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_void(&self) -> bool {
|
||||||
|
self.basetype == "void" && self.reference.is_none()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CommandMap<'a> = HashMap<vkxml::Identifier, &'a vkxml::Command>;
|
pub type CommandMap<'a> = HashMap<vkxml::Identifier, &'a vkxml::Command>;
|
||||||
|
@ -901,12 +911,6 @@ fn generate_function_pointers<'a>(
|
||||||
.collect();
|
.collect();
|
||||||
let expanded_params_ref = &expanded_params;
|
let expanded_params_ref = &expanded_params;
|
||||||
|
|
||||||
let return_types: Vec<_> = commands
|
|
||||||
.iter()
|
|
||||||
.map(|cmd| cmd.return_type.type_tokens(true))
|
|
||||||
.collect();
|
|
||||||
let return_types_ref = &return_types;
|
|
||||||
|
|
||||||
let pfn_names: Vec<_> = commands_pfn
|
let pfn_names: Vec<_> = commands_pfn
|
||||||
.iter()
|
.iter()
|
||||||
.map(|cmd| format_ident!("{}", format!("PFN_{}", cmd.name.as_str())))
|
.map(|cmd| format_ident!("{}", format!("PFN_{}", cmd.name.as_str())))
|
||||||
|
@ -930,21 +934,28 @@ fn generate_function_pointers<'a>(
|
||||||
.collect();
|
.collect();
|
||||||
let signature_params_ref = &signature_params;
|
let signature_params_ref = &signature_params;
|
||||||
|
|
||||||
let pfn_return_types: Vec<_> = commands
|
let return_types: Vec<_> = commands
|
||||||
.iter()
|
.iter()
|
||||||
.map(|cmd| cmd.return_type.type_tokens(true))
|
.map(|cmd| {
|
||||||
|
if cmd.return_type.is_void() {
|
||||||
|
quote!()
|
||||||
|
} else {
|
||||||
|
let ret_ty_tokens = cmd.return_type.type_tokens(true);
|
||||||
|
quote!(-> #ret_ty_tokens)
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let pfn_return_types_ref = &pfn_return_types;
|
let return_types_ref = &return_types;
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#(
|
#(
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub type #pfn_names_ref = extern "system" fn(#(#signature_params_ref),*) -> #pfn_return_types_ref;
|
pub type #pfn_names_ref = extern "system" fn(#(#signature_params_ref),*) #return_types_ref;
|
||||||
)*
|
)*
|
||||||
|
|
||||||
pub struct #ident {
|
pub struct #ident {
|
||||||
#(
|
#(
|
||||||
pub #names_ref: extern "system" fn(#expanded_params_ref) -> #return_types_ref,
|
pub #names_ref: extern "system" fn(#expanded_params_ref) #return_types_ref,
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +977,7 @@ fn generate_function_pointers<'a>(
|
||||||
#(
|
#(
|
||||||
#names_ref: unsafe {
|
#names_ref: unsafe {
|
||||||
|
|
||||||
extern "system" fn #names_ref1 (#expanded_params_unused) -> #return_types_ref {
|
extern "system" fn #names_ref1 (#expanded_params_unused) #return_types_ref {
|
||||||
panic!(concat!("Unable to load ", stringify!(#names_ref2)))
|
panic!(concat!("Unable to load ", stringify!(#names_ref2)))
|
||||||
}
|
}
|
||||||
let raw_name = stringify!(#raw_names_ref);
|
let raw_name = stringify!(#raw_names_ref);
|
||||||
|
@ -984,7 +995,7 @@ fn generate_function_pointers<'a>(
|
||||||
}
|
}
|
||||||
#(
|
#(
|
||||||
#[doc = #khronos_links]
|
#[doc = #khronos_links]
|
||||||
pub unsafe fn #names_ref(&self, #expanded_params_ref) -> #return_types_ref {
|
pub unsafe fn #names_ref(&self, #expanded_params_ref) #return_types_ref {
|
||||||
(self.#names_left)(#(#params_names,)*)
|
(self.#names_left)(#(#params_names,)*)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
@ -2060,7 +2071,12 @@ pub fn generate_handle(handle: &vkxml::Handle) -> Option<TokenStream> {
|
||||||
}
|
}
|
||||||
fn generate_funcptr(fnptr: &vkxml::FunctionPointer) -> TokenStream {
|
fn generate_funcptr(fnptr: &vkxml::FunctionPointer) -> TokenStream {
|
||||||
let name = format_ident!("{}", fnptr.name.as_str());
|
let name = format_ident!("{}", fnptr.name.as_str());
|
||||||
|
let ret_ty_tokens = if fnptr.return_type.is_void() {
|
||||||
|
quote!()
|
||||||
|
} else {
|
||||||
let ret_ty_tokens = fnptr.return_type.type_tokens(true);
|
let ret_ty_tokens = fnptr.return_type.type_tokens(true);
|
||||||
|
quote!(-> #ret_ty_tokens)
|
||||||
|
};
|
||||||
let params = fnptr.param.iter().map(|field| {
|
let params = fnptr.param.iter().map(|field| {
|
||||||
let ident = field.param_ident();
|
let ident = field.param_ident();
|
||||||
let type_tokens = field.type_tokens(true);
|
let type_tokens = field.type_tokens(true);
|
||||||
|
@ -2072,7 +2088,7 @@ fn generate_funcptr(fnptr: &vkxml::FunctionPointer) -> TokenStream {
|
||||||
quote! {
|
quote! {
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[doc = #khronos_link]
|
#[doc = #khronos_link]
|
||||||
pub type #name = Option<unsafe extern "system" fn(#(#params),*) -> #ret_ty_tokens>;
|
pub type #name = Option<unsafe extern "system" fn(#(#params),*) #ret_ty_tokens>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue