From 767c821cd1f4b609fe43fee672b76af755b37123 Mon Sep 17 00:00:00 2001 From: Leon Matthes Date: Wed, 10 Aug 2022 17:20:02 +0200 Subject: [PATCH] Remove CppObj This will move all invokables onto MyObjectQt and remove the need for the CppObj. --- cxx-qt-gen/src/extract.rs | 161 ++----- cxx-qt-gen/src/gen_cpp.rs | 33 +- cxx-qt-gen/src/gen_rs.rs | 409 ++++++------------ cxx-qt-gen/src/parser/cxxqtdata.rs | 29 +- cxx-qt-gen/src/writer/rust/mod.rs | 10 +- cxx-qt-gen/test_inputs/handlers.rs | 4 +- cxx-qt-gen/test_inputs/invokables.rs | 29 +- cxx-qt-gen/test_inputs/naming.rs | 3 +- cxx-qt-gen/test_inputs/signals.rs | 6 +- cxx-qt-gen/test_inputs/types_qt_invokable.rs | 30 +- cxx-qt-gen/test_outputs/custom_default.rs | 39 +- cxx-qt-gen/test_outputs/handlers.rs | 60 +-- cxx-qt-gen/test_outputs/invokables.cpp | 33 +- cxx-qt-gen/test_outputs/invokables.h | 3 - cxx-qt-gen/test_outputs/invokables.rs | 136 +++--- cxx-qt-gen/test_outputs/naming.cpp | 2 +- cxx-qt-gen/test_outputs/naming.rs | 48 +- cxx-qt-gen/test_outputs/passthrough.rs | 39 +- cxx-qt-gen/test_outputs/properties.rs | 49 +-- cxx-qt-gen/test_outputs/signals.rs | 56 +-- .../test_outputs/types_primitive_property.rs | 119 +---- cxx-qt-gen/test_outputs/types_qt_invokable.rs | 172 +++----- cxx-qt-gen/test_outputs/types_qt_property.rs | 160 +------ cxx-qt-lib/src/lib.rs | 6 +- examples/demo_threading/src/lib.rs | 30 +- examples/qml_extension_plugin/core/src/lib.rs | 17 +- examples/qml_features/src/lib.rs | 6 +- examples/qml_features/src/mock_qt_types.rs | 151 ++++--- .../qml_features/src/rust_obj_invokables.rs | 15 +- examples/qml_features/src/serialisation.rs | 8 +- examples/qml_features/src/signals.rs | 21 +- examples/qml_features/src/types.rs | 10 +- examples/qml_minimal/src/lib.rs | 5 +- examples/qml_with_threaded_logic/src/lib.rs | 49 ++- tests/basic_cxx_qt/src/data.rs | 8 +- tests/basic_cxx_qt/src/lib.rs | 24 +- 36 files changed, 666 insertions(+), 1314 deletions(-) diff --git a/cxx-qt-gen/src/extract.rs b/cxx-qt-gen/src/extract.rs index e2ec92ffe..a0d4c121e 100644 --- a/cxx-qt-gen/src/extract.rs +++ b/cxx-qt-gen/src/extract.rs @@ -23,27 +23,6 @@ pub(crate) struct CppRustIdent { #[derive(Debug, PartialEq)] pub(crate) enum QtTypes { Bool, - /// A CppObj which is being passed as a parameter in a method - CppObj { - /// The ident of the type for C++, eg the MyObject or CppObj from: - /// C++ - MyObject or cxx_qt::sub_object::CppObj - cpp_type_idents: Vec, - /// A cache of the C++ type as a string with the namespace - /// eg "cxx_qt::module::CppObj" - cpp_type_idents_string: String, - /// The ident of the type for Rust, eg the MyObject or CppObj from: - /// Rust - MyObject or crate::sub_object::CppObj - rust_type_idents: Vec, - /// The combined name of the type, this is a single word which is used - /// as the type name of the C++ type in the Rust cxx bridge - /// eg MyObject or SubObject - /// This needs the match the name of the C++ class without namespace - /// as we add this in the macro attribute - // - // TODO: later can we use the fully qualified path - // eg crate::my_module::CppObj to Crate_MyModule_CppObj? - combined_name: Ident, - }, F32, F64, I8, @@ -65,25 +44,19 @@ pub(crate) enum QtTypes { U8, U16, U32, - UniquePtr { - inner: Box, - }, + UniquePtr { inner: Box }, Unknown, } impl QtTypes { /// Whether this type is allowed to be a ref mut fn ref_mut_is_valid(&self) -> bool { - match self { - Self::CppObj { .. } => true, - _others => false, - } + false } /// Whether this type is opaque so will be a UniquePtr when returned from Rust to C++ pub(crate) fn is_opaque(&self) -> bool { match self { - Self::CppObj { .. } => true, Self::UniquePtr { .. } => true, _others => false, } @@ -117,7 +90,7 @@ pub(crate) struct Invokable { /// The ident of the function pub(crate) ident: CppRustIdent, /// If the invokable needs a wrapper, this is it's ident - pub(crate) ident_wrapper: Option, + pub(crate) ident_wrapper: CppRustIdent, /// The parameters that the function takes in pub(crate) parameters: Vec, /// The return type information @@ -224,12 +197,6 @@ fn extract_qt_type( // We can assume that idents has an entry at index zero, because there is one entry match idents[0].to_string().as_str() { "bool" => Ok(QtTypes::Bool), - "CppObj" => Ok(QtTypes::CppObj { - cpp_type_idents: vec![qt_ident.clone()], - cpp_type_idents_string: qt_ident.to_string(), - rust_type_idents: vec![quote::format_ident!("{}Qt", qt_ident)], - combined_name: qt_ident.clone(), - }), "f32" => Ok(QtTypes::F32), "f64" => Ok(QtTypes::F64), "i8" => Ok(QtTypes::I8), @@ -379,6 +346,10 @@ pub(crate) fn extract_method_params( ); }; + if parameter_ident == "self" { + return Ok(None); + } + // Try to extract the type of the parameter match extract_type_ident(ty, qt_ident) { Ok(result) => type_ident = result, @@ -426,11 +397,36 @@ pub(crate) fn extract_method_params( // Note that self: Box is parsed as FnArg::Typed not FnArg::Receiver so will be false // but we don't use this case with CXX, so this can be ignored. fn is_method_mutable(method: &ImplItemMethod) -> bool { - if let Some(FnArg::Receiver(Receiver { mutability, .. })) = method.sig.inputs.first() { - return mutability.is_some(); - } + match method.sig.inputs.first() { + Some(FnArg::Receiver(Receiver { mutability, .. })) => mutability.is_some(), + Some(FnArg::Typed(PatType { ty, pat, .. })) => { + if let Pat::Ident(PatIdent { ident, .. }) = pat.as_ref() { + if ident != "self" { + return false; + } + } + if let Type::Path(TypePath { path, .. }) = ty.as_ref() { + if !crate::syntax::path::path_compare_str(path, &["Pin"]) { + return false; + } - false + if let Some(last) = path.segments.last() { + if let PathArguments::AngleBracketed(args) = &last.arguments { + // TODO: Maybe check that the reference is of type `Self`. + if let Some(GenericArgument::Type(Type::Reference(TypeReference { + mutability: Some(_), + .. + }))) = args.args.first() + { + return true; + } + } + } + } + false + } + _ => false, + } } fn extract_invokable(method: &ImplItemMethod, qt_ident: &Ident) -> Result { @@ -479,21 +475,10 @@ fn extract_invokable(method: &ImplItemMethod, qt_ident: &Ident) -> Result bool { match self { Self::Bool => false, - Self::CppObj { .. } => false, Self::F32 | Self::F64 => false, Self::I8 | Self::I16 | Self::I32 => false, Self::QColor => true, @@ -95,18 +94,12 @@ impl CppType for QtTypes { /// Whether this type is a Pin this is then used in method definitions /// to add *this to this or *arg to arg. fn is_pin(&self) -> bool { - match self { - Self::CppObj { .. } => true, - _others => false, - } + false } /// Whether this type is a pointer fn is_ptr(&self) -> bool { - match self { - Self::CppObj { .. } => true, - _other => false, - } + false } /// Whether this type is a reference (when used as an input to methods) @@ -120,7 +113,6 @@ impl CppType for QtTypes { fn is_ref(&self) -> bool { match self { Self::Bool => false, - Self::CppObj { .. } => false, Self::F32 | Self::F64 => false, Self::I8 | Self::I16 | Self::I32 => false, Self::QColor => true, @@ -145,20 +137,13 @@ impl CppType for QtTypes { /// Whether this type is_this, this is used to determine if the ident is changed in method /// definitions and if the parameter should be skipped in method declarations fn is_this(&self) -> bool { - match self { - Self::CppObj { .. } => true, - _others => false, - } + false } /// The C++ type name of the CppType fn type_ident(&self) -> &str { match self { Self::Bool => "bool", - Self::CppObj { - cpp_type_idents_string, - .. - } => cpp_type_idents_string, Self::F32 => "float", Self::F64 => "double", Self::I8 => "qint8", @@ -339,12 +324,12 @@ fn generate_invokables_cpp( let body = format!( "m_rustObj->{ident}({parameter_names})", // If we are a pointer to a CppObj then we need a wrapper - ident = if let Some(ident_wrapper) = &invokable.ident_wrapper { - ident_wrapper.cpp_ident.to_string() - } else { - invokable.ident.cpp_ident.to_string() - }, - parameter_names = parameters.names.join(", ") + ident = invokable.ident_wrapper.cpp_ident, + parameter_names = (vec!["*this".to_owned()] + .into_iter() + .chain(parameters.names.into_iter())) + .collect::>() + .join(", ") ); // Cache the return ident as it's used in both header and source diff --git a/cxx-qt-gen/src/gen_rs.rs b/cxx-qt-gen/src/gen_rs.rs index c5969b49e..b22fa87c7 100644 --- a/cxx-qt-gen/src/gen_rs.rs +++ b/cxx-qt-gen/src/gen_rs.rs @@ -111,6 +111,82 @@ impl RustType for QtTypes { } } +fn generate_invokable_cxx_declaration(obj: &QObject, i: &Invokable) -> TokenStream { + let rust_class_name = &obj.original_rust_struct.ident; + let cpp_class_name = format_ident!("{}Qt", rust_class_name); + + // Cache the ident and parameters as they are used multiple times later + let (ident, ident_cpp_str) = ( + &i.ident_wrapper.rust_ident, + i.ident_wrapper.cpp_ident.to_string(), + ); + let parameters = &i.parameters; + let mutablility = if i.mutable { + Some(quote! { mut }) + } else { + None + }; + + // TODO: invokables need to also become freestanding functions that + // take as input a reference to both the Rs class and the CppObject + // inside a wrapper. The functions that are impl'ed on the Rs class + // will then simply create the wrapper and call the free functions. + // + // As a first step we could maybe just add a `cpp: Pin<&mut FFICppObj>` + // argument to invokables so that users can manually wrap it. + + // Determine if the invokable has any parameter + let mut parameters_quotes = Vec::new(); + + let cpp_type = if i.mutable { + quote! { Pin<&mut #cpp_class_name> } + } else { + quote! { &#cpp_class_name } + }; + + parameters_quotes.push(quote! { cpp: #cpp_type }); + + for p in parameters { + // Cache the name and type + let ident = &p.ident; + + // If the type is Pin then we need to change extract differently + let type_ident = &p.type_ident.qt_type.cxx_bridge_type_ident(); + let is_ref = if p.type_ident.is_ref { + quote! {&} + } else { + quote! {} + }; + let is_mut = if p.type_ident.is_mut { + quote! {mut} + } else { + quote! {} + }; + parameters_quotes.push(quote! { + #ident: #is_ref #is_mut #type_ident + }); + } + // Determine if there is a return type + let return_expr = if let Some(return_type) = &i.return_type { + // Cache and build the return type + let type_ident = &return_type.qt_type.cxx_bridge_type_ident(); + if return_type.qt_type.is_opaque() { + Some(quote! { -> UniquePtr<#type_ident> }) + } else if return_type.is_ref { + Some(quote! { -> &#type_ident }) + } else { + Some(quote! { -> #type_ident }) + } + } else { + None + }; + + quote! { + #[cxx_name = #ident_cpp_str] + fn #ident(self: &#mutablility #rust_class_name, #(#parameters_quotes),*) #return_expr; + } +} + /// Generate Rust code that used CXX to interact with the C++ code generated for a QObject pub fn generate_qobject_cxx(obj: &QObject) -> Result { // Cache the original and rust class names, these are used multiple times later @@ -133,112 +209,7 @@ pub fn generate_qobject_cxx(obj: &QObject) -> Result { // TODO: later support a cxx_qt_name attribute on invokables to allow for renaming // to a custom name for C++ or Rust side? for i in &obj.invokables { - // Cache the ident and parameters as they are used multiple times later - let (ident, ident_cpp_str) = if let Some(ident_wrapper) = &i.ident_wrapper { - ( - &ident_wrapper.rust_ident, - ident_wrapper.cpp_ident.to_string(), - ) - } else { - (&i.ident.rust_ident, i.ident.cpp_ident.to_string()) - }; - let parameters = &i.parameters; - let mutablility = if i.mutable { - Some(quote! { mut }) - } else { - None - }; - - // TODO: invokables need to also become freestanding functions that - // take as input a reference to both the Rs class and the CppObject - // inside a wrapper. The functions that are impl'ed on the Rs class - // will then simply create the wrapper and call the free functions. - // - // As a first step we could maybe just add a `cpp: Pin<&mut FFICppObj>` - // argument to invokables so that users can manually wrap it. - - // Determine if the invokable has any parameter - if parameters.is_empty() { - // Determine if there is a return type - if let Some(return_type) = &i.return_type { - // Cache and build the return type - let type_ident = &return_type.qt_type.cxx_bridge_type_ident(); - let type_ident = if return_type.qt_type.is_opaque() { - quote! { UniquePtr<#type_ident> } - } else if return_type.is_ref { - quote! { &#type_ident } - } else { - quote! { #type_ident } - }; - - rs_functions.push(quote! { - #[cxx_name = #ident_cpp_str] - fn #ident(self: &#mutablility #rust_class_name) -> #type_ident; - }); - } else { - rs_functions.push(quote! { - #[cxx_name = #ident_cpp_str] - fn #ident(self: &#mutablility #rust_class_name); - }); - } - } else { - // Build a list of quotes of the parameter name and type - let mut parameters_quotes = Vec::new(); - for p in parameters { - // Cache the name and type - let ident = &p.ident; - - // If the type is Pin then we need to change extract differently - match &p.type_ident.qt_type { - QtTypes::CppObj { - rust_type_idents, .. - } => { - parameters_quotes.push(quote! { - #ident: Pin<&mut #(#rust_type_idents)::*> - }); - } - _others => { - let type_ident = &p.type_ident.qt_type.cxx_bridge_type_ident(); - let is_ref = if p.type_ident.is_ref { - quote! {&} - } else { - quote! {} - }; - let is_mut = if p.type_ident.is_mut { - quote! {mut} - } else { - quote! {} - }; - parameters_quotes.push(quote! { - #ident: #is_ref #is_mut #type_ident - }); - } - }; - } - - // Determine if there is a return type and if it's a reference - if let Some(return_type) = &i.return_type { - // Cache and build the return type - let type_ident = &return_type.qt_type.cxx_bridge_type_ident(); - let type_ident = if return_type.qt_type.is_opaque() { - quote! { UniquePtr<#type_ident> } - } else if return_type.is_ref { - quote! { &#type_ident } - } else { - quote! { #type_ident } - }; - - rs_functions.push(quote! { - #[cxx_name = #ident_cpp_str] - fn #ident(self: &#mutablility #rust_class_name, #(#parameters_quotes),*) -> #type_ident; - }); - } else { - rs_functions.push(quote! { - #[cxx_name = #ident_cpp_str] - fn #ident(self: &#mutablility #rust_class_name, #(#parameters_quotes),*); - }); - } - } + rs_functions.push(generate_invokable_cxx_declaration(obj, i)); } // Add getters/setters/notify from properties @@ -413,79 +384,6 @@ pub fn generate_qobject_cxx(obj: &QObject) -> Result { syn::parse2::(output.into_token_stream()).map_err(|err| err.to_compile_error()) } -fn generate_property_methods_rs(obj: &QObject) -> Result, TokenStream> { - // Build a list of property methods impls - let mut property_methods = Vec::new(); - - for property in &obj.properties { - let qt_type = if let QtTypes::UniquePtr { inner } = &property.type_ident.qt_type { - &**inner - } else { - &property.type_ident.qt_type - }; - let rust_param_type = qt_type.cxx_qt_lib_type(); - // When the output type is opaque we pass by value rather than ref - // even though it's a non trivial type - let rust_param_type = if !qt_type.is_opaque() && qt_type.is_ref() { - quote! {&#rust_param_type} - } else { - quote! {#rust_param_type} - }; - - let cpp_getter_ident = &property.getter.as_ref().unwrap().rust_ident; - let cpp_setter_ident = &property.setter.as_ref().unwrap().rust_ident; - - if let QtTypes::CppObj { .. } = property.type_ident.qt_type { - let ident = &property.ident.rust_ident; - let take_ident = format_ident!("take_{}", ident); - let give_ident = format_ident!("give_{}", ident); - - property_methods.push(quote! { - pub fn #take_ident(&mut self) -> #rust_param_type { - self.cpp.as_mut().#take_ident() - } - }); - - property_methods.push(quote! { - pub fn #give_ident(&mut self, value: #rust_param_type) { - self.cpp.as_mut().#give_ident(value); - } - }); - } else { - if let Some(getter) = &property.getter { - // Generate a getter using the rust ident - let getter_ident = &getter.rust_ident; - - property_methods.push(quote! { - pub fn #getter_ident(&self) -> #rust_param_type { - self.cpp.#cpp_getter_ident() - } - }); - } - - if let Some(setter) = &property.setter { - // Generate a setter using the rust ident - let setter_ident = &setter.rust_ident; - if qt_type.is_opaque() { - property_methods.push(quote! { - pub fn #setter_ident(&mut self, value: #rust_param_type) { - self.cpp.as_mut().#cpp_setter_ident(&value); - } - }); - } else { - property_methods.push(quote! { - pub fn #setter_ident(&mut self, value: #rust_param_type) { - self.cpp.as_mut().#cpp_setter_ident(value); - } - }); - }; - } - } - } - - Ok(property_methods) -} - fn generate_signal_methods_rs(obj: &QObject) -> Result, TokenStream> { let mut signal_methods = Vec::new(); let mut queued_cases = Vec::new(); @@ -528,17 +426,17 @@ fn generate_signal_methods_rs(obj: &QObject) -> Result, TokenSt let signal_ident = &signal.signal_ident.rust_ident; queued_cases.push(quote! { - #ident::#enum_ident { #(#parameters),* } => self.cpp.as_mut().#emit_ident(#(#parameters_to_value_queued),*), + #ident::#enum_ident { #(#parameters),* } => self.#emit_ident(#(#parameters_to_value_queued),*), }); immediate_cases.push(quote! { - #ident::#enum_ident { #(#parameters),* } => self.cpp.as_mut().#signal_ident(#(#parameters_to_value_immediate),*), + #ident::#enum_ident { #(#parameters),* } => self.#signal_ident(#(#parameters_to_value_immediate),*), }); } if !queued_cases.is_empty() { signal_methods.push(quote! { - pub fn emit_queued(&mut self, signal: #ident) { + pub fn emit_queued(self: Pin<&mut Self>, signal: #ident) { match signal { #(#queued_cases)* } @@ -548,7 +446,7 @@ fn generate_signal_methods_rs(obj: &QObject) -> Result, TokenSt if !immediate_cases.is_empty() { signal_methods.push(quote! { - pub unsafe fn emit_immediate(&mut self, signal: #ident) { + pub unsafe fn emit_immediate(self: Pin<&mut Self>, signal: #ident) { match signal { #(#immediate_cases)* } @@ -604,6 +502,13 @@ fn invokable_generate_wrapper( let mut output_parameters = vec![]; let mut wrappers = vec![]; + let cpp_type = if invokable.mutable { + quote! { std::pin::Pin<&mut FFICppObj> } + } else { + quote! { &FFICppObj } + }; + input_parameters.push(quote! { cpp: #cpp_type }); + for param in &invokable.parameters { let param_ident = ¶m.ident; let is_mut = if param.type_ident.is_mut { @@ -617,49 +522,21 @@ fn invokable_generate_wrapper( quote! {} }; - if let QtTypes::CppObj { - rust_type_idents, .. - } = ¶m.type_ident.qt_type - { - // Create Rust idents with CppObj and FFICppObj at the end - let rust_idents_module = rust_type_idents - .iter() - .take(rust_type_idents.len() - 1) - .cloned() - .collect::>(); - let rust_idents_ffi = rust_idents_module - .iter() - .cloned() - .chain(vec![format_ident!("FFICppObj")]); - let rust_idents_cpp_obj = rust_idents_module - .iter() - .cloned() - .chain(vec![format_ident!("CppObj")]); - - input_parameters - .push(quote! { #param_ident: std::pin::Pin<&mut #(#rust_idents_ffi)::*> }); - + // If we are an opaque input type we need to convert to the Rust type + // + // And then keep the ref and mut state of the parameter + if param.type_ident.qt_type.is_opaque() { wrappers.push(quote! { - let mut #param_ident = #(#rust_idents_cpp_obj)::*::new(#param_ident); + let #is_mut #param_ident = #param_ident.to_rust(); }); + output_parameters.push(quote! { #is_ref #is_mut #param_ident }); } else { - // If we are an opaque input type we need to convert to the Rust type - // - // And then keep the ref and mut state of the parameter - if param.type_ident.qt_type.is_opaque() { - wrappers.push(quote! { - let #is_mut #param_ident = #param_ident.to_rust(); - }); - - output_parameters.push(quote! { #is_ref #is_mut #param_ident }); - } else { - output_parameters.push(quote! { #param_ident }); - } - - let param_type = param.type_ident.qt_type.cxx_qt_lib_type(); - input_parameters.push(quote! { #param_ident: #is_ref #is_mut #param_type }); + output_parameters.push(quote! { #param_ident }); } + + let param_type = param.type_ident.qt_type.cxx_qt_lib_type(); + input_parameters.push(quote! { #param_ident: #is_ref #is_mut #param_type }); } // If we are an opaque return type then we need to convert into the C++ type @@ -669,14 +546,14 @@ fn invokable_generate_wrapper( Ok(quote! { pub fn #ident_wrapper(&#mutablility self, #(#input_parameters),*) -> #return_type_ident { #(#wrappers)* - return self.#ident(#(#output_parameters),*); + return cpp.#ident(#(#output_parameters),*); } }) } else { Ok(quote! { pub fn #ident_wrapper(&#mutablility self, #(#input_parameters),*) { #(#wrappers)* - self.#ident(#(#output_parameters),*); + cpp.#ident(#(#output_parameters),*); } }) } @@ -686,7 +563,7 @@ fn invokable_generate_wrapper( pub fn generate_qobject_rs(obj: &QObject) -> Result { // Cache the rust class name let rust_class_name = &obj.original_rust_struct.ident; - let rust_wrapper_name = format_ident!("CppObj"); + let class_name_cpp = format_ident!("{}Qt", rust_class_name); // Generate cxx block let cxx_block = generate_qobject_cxx(obj)?; @@ -701,13 +578,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { .properties .iter() .zip(&obj.original_data_struct.fields) - .filter_map(|(prop, field)| { - if let QtTypes::CppObj { .. } = prop.type_ident.qt_type { - None - } else { - Some((&prop.type_ident.qt_type, field)) - } - }) + .map(|(prop, field)| (&prop.type_ident.qt_type, field)) .collect::>(); // TODO: we need to update this to only store fields defined as "private" once we have an API for that let data_struct = build_struct_with_fields( @@ -718,7 +589,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { .collect::>(), ); - // Build a converter for Data -> CppObj + // Build a converter for QObject -> Data let data_struct_impl = { let mut fields_into = vec![]; // If there are no filtered fields then use _value @@ -739,24 +610,17 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { } quote! { - impl<'a> From<&#rust_wrapper_name<'a>> for #data_struct_name { - fn from(#value_ident: &#rust_wrapper_name<'a>) -> Self { + impl From<&#class_name_cpp> for #data_struct_name { + fn from(#value_ident: &#class_name_cpp) -> Self { Self { #(#fields_into),* } } } - - impl<'a> From<&mut #rust_wrapper_name<'a>> for #data_struct_name { - fn from(#value_ident: &mut #rust_wrapper_name<'a>) -> Self { - Self::from(&*#value_ident) - } - } } }; // Generate property methods from the object - let property_methods = generate_property_methods_rs(obj)?; let signal_methods = generate_signal_methods_rs(obj)?; let signal_enum = obj.original_signal_enum.as_ref(); @@ -764,11 +628,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { let invokable_method_wrappers = obj .invokables .iter() - .filter_map(|i| { - i.ident_wrapper - .as_ref() - .map(|ident_wrapper| invokable_generate_wrapper(i, &ident_wrapper.rust_ident)) - }) + .map(|i| invokable_generate_wrapper(i, &i.ident_wrapper.rust_ident)) .collect::, TokenStream>>()?; let invokable_methods = obj .invokables @@ -792,8 +652,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { let handle_update_request = if obj.handle_updates_impl.is_some() { quote! { pub fn call_handle_update_request(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { - let mut cpp = CppObj::new(cpp); - self.handle_update_request(&mut cpp); + cpp.handle_update_request(); } } } else { @@ -803,20 +662,11 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { let rust_struct_impl = quote! { impl #rust_class_name { #(#invokable_method_wrappers)* - #(#invokable_methods)* - #(#methods)* #handle_update_request } }; - // Create a struct that wraps the CppObject with a nicer interface - let wrapper_struct = quote! { - pub struct #rust_wrapper_name<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - }; - // TODO: eventually we want so support grabbing values from sub objects too let mut grab_values = vec![]; for (qt_type, field) in &data_fields_no_ptr { @@ -826,7 +676,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { if qt_type.is_opaque() { grab_values.push(quote! { - self.#setter_name(data.#field_name.as_ref().unwrap()); + self.as_mut().#setter_name(data.#field_name.as_ref().unwrap()); }); } else { let is_ref = if qt_type.is_ref() { @@ -836,34 +686,20 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { }; grab_values.push(quote! { - self.#setter_name(#is_ref data.#field_name); + self.as_mut().#setter_name(#is_ref data.#field_name); }); } } } - let update_requester = if obj.handle_updates_impl.is_some() { - quote! { - pub fn update_requester(&mut self) -> cxx_qt_lib::UpdateRequester { - cxx_qt_lib::UpdateRequester::from_unique_ptr(self.cpp.as_mut().update_requester()) - } - } - } else { - quote! {} - }; - - let wrapper_struct_impl = quote! { - impl<'a> #rust_wrapper_name<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } + let qobject_impl = quote! { + impl #class_name_cpp { + #(#invokable_methods)* + #(#methods)* - #(#property_methods)* #(#signal_methods)* - #update_requester - - pub fn grab_values_from_data(&mut self, mut data: #data_struct_name) { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: #data_struct_name) { #(#grab_values)* } } @@ -874,7 +710,16 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { use_traits.push(quote! { use cxx_qt_lib::UpdateRequestHandler; }); } - let handle_updates_impl = &obj.handle_updates_impl; + let handle_updates_impl = if let Some(updates_impl) = &obj.handle_updates_impl { + let handle_updates_inner = &updates_impl.items; + quote! { + impl UpdateRequestHandler for #class_name_cpp { + #(#handle_updates_inner),* + } + } + } else { + quote! {} + }; // Create the namespace for internal use // @@ -893,6 +738,8 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { // later this code will be moved into a generator phase let cxx_qt_mod_fake: ItemMod = syn::parse2::(quote! { mod fake { + use std::pin::Pin; + #(#use_traits)* #signal_enum @@ -901,9 +748,7 @@ pub fn generate_qobject_rs(obj: &QObject) -> Result { #rust_struct_impl - #wrapper_struct - - #wrapper_struct_impl + #qobject_impl #data_struct diff --git a/cxx-qt-gen/src/parser/cxxqtdata.rs b/cxx-qt-gen/src/parser/cxxqtdata.rs index 97bd167fe..74736efbe 100644 --- a/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -102,6 +102,20 @@ impl ParsedCxxQtData { // Convert the path to a single ident, and error if it isn't .get_mut(&path_to_single_ident(&qobject_path)?) { + // If we are the UpdateRequestHandler, then we need to store in list + // + // TODO: once impl UpdateRequestHandler is removed this block can go + if let Some(trait_) = &imp.trait_ { + if let Some(first) = trait_.1.segments.first() { + if first.ident == "UpdateRequestHandler" { + // We know that there is only one impl block because the compiler + // already ensures this. + qobject.update_requester_handler = Some(imp.clone()); + return Ok(None); + } + } + } + // Extract the ImplItem's from each Impl block qobject.parse_impl_items(&imp.items)?; } else { @@ -122,19 +136,6 @@ impl ParsedCxxQtData { return Ok(None); // Find if we are an impl block for a qobject } else if let Some(qobject) = self.qobjects.get_mut(&path_to_single_ident(path)?) { - // If we are the UpdateRequestHandler, then we need to store in list - // - // TODO: once impl UpdateRequestHandler is removed this block can go - if let Some(trait_) = &imp.trait_ { - if let Some(first) = trait_.1.segments.first() { - if first.ident == "UpdateRequestHandler" { - // We assume that there is only one impl block from the compiler - qobject.update_requester_handler = Some(imp.clone()); - return Ok(None); - } - } - } - qobject.others.push(Item::Impl(imp)); return Ok(None); } @@ -511,7 +512,7 @@ mod tests { let mut cxx_qt_data = create_parsed_cxx_qt_data(); let item: Item = tokens_to_syn(quote! { - impl UpdateRequestHandler for MyObject { + impl UpdateRequestHandler for cxx_qt::QObject { fn method() {} } }); diff --git a/cxx-qt-gen/src/writer/rust/mod.rs b/cxx-qt-gen/src/writer/rust/mod.rs index f62bf81d0..e1b7f1353 100644 --- a/cxx-qt-gen/src/writer/rust/mod.rs +++ b/cxx-qt-gen/src/writer/rust/mod.rs @@ -87,9 +87,8 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut #cpp_struct_ident>) { + cpp.grab_values_from_data(Data::default()); } } } @@ -203,9 +202,8 @@ mod tests { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } } diff --git a/cxx-qt-gen/test_inputs/handlers.rs b/cxx-qt-gen/test_inputs/handlers.rs index 8372defcf..4aa1ebecf 100644 --- a/cxx-qt-gen/test_inputs/handlers.rs +++ b/cxx-qt-gen/test_inputs/handlers.rs @@ -16,8 +16,8 @@ mod ffi { #[derive(Default)] pub struct MyObject; - impl UpdateRequestHandler for MyObject { - fn handle_update_request(&mut self, _cpp: &mut CppObj) { + impl UpdateRequestHandler for cxx_qt::QObject { + fn handle_update_request(self: Pin<&mut Self>) { println!("update") } } diff --git a/cxx-qt-gen/test_inputs/invokables.rs b/cxx-qt-gen/test_inputs/invokables.rs index c9ed37cfc..989d21f1e 100644 --- a/cxx-qt-gen/test_inputs/invokables.rs +++ b/cxx-qt-gen/test_inputs/invokables.rs @@ -19,17 +19,7 @@ mod ffi { } #[qinvokable] - pub fn invokable_cpp_obj(&self, cpp: &mut CppObj) { - println!("cppobj"); - } - - #[qinvokable] - pub fn invokable_mutable(&mut self) { - println!("This method is mutable!"); - } - - #[qinvokable] - pub fn invokable_mutable_cpp_obj(&mut self, cpp: &mut CppObj) { + pub fn invokable_mutable(self: Pin<&mut Self>) { println!("This method is mutable!"); } @@ -44,22 +34,17 @@ mod ffi { } #[qinvokable] - pub fn invokable_parameters_cpp_obj(&self, primitive: i32, cpp: &mut CppObj) { - println!("{}", primitive); - } - - #[qinvokable] - pub fn invokable_return_opaque(&mut self) -> UniquePtr { + pub fn invokable_return_opaque(self: Pin<&mut Self>) -> UniquePtr { cxx_qt_lib::QColor::from_rgba(255, 0, 0, 0) } #[qinvokable] - pub fn invokable_return_primitive(&mut self) -> i32 { + pub fn invokable_return_primitive(self: Pin<&mut Self>) -> i32 { 2 } #[qinvokable] - pub fn invokable_return_static(&mut self) -> UniquePtr { + pub fn invokable_return_static(self: Pin<&mut Self>) -> UniquePtr { QString::from_str("static") } @@ -67,14 +52,10 @@ mod ffi { println!("C++ context method"); } - pub fn cpp_context_method_mutable(&mut self) { + pub fn cpp_context_method_mutable(self: Pin<&mut Self>) { println!("mutable method"); } - pub fn cpp_context_method_cpp_obj(&mut self, cpp: &mut CppObj) { - println!("cppobj"); - } - pub fn cpp_context_method_return_opaque(&self) -> UniquePtr { cxx_qt_lib::QColor::from_rgba(255, 0, 0, 0) } diff --git a/cxx-qt-gen/test_inputs/naming.rs b/cxx-qt-gen/test_inputs/naming.rs index 42120694b..dc2c20947 100644 --- a/cxx-qt-gen/test_inputs/naming.rs +++ b/cxx-qt-gen/test_inputs/naming.rs @@ -15,8 +15,9 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn invokable_name(&self) { + pub fn invokable_name(self: Pin<&mut Self>) { println!("Bye from Rust!"); + self.as_mut().set_property_name(5); } } } diff --git a/cxx-qt-gen/test_inputs/signals.rs b/cxx-qt-gen/test_inputs/signals.rs index f5eb7ac75..3da2bfb57 100644 --- a/cxx-qt-gen/test_inputs/signals.rs +++ b/cxx-qt-gen/test_inputs/signals.rs @@ -26,12 +26,12 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn invokable(&self, cpp: &mut CppObj) { + pub fn invokable(self: Pin<&mut Self>) { unsafe { - cpp.emit_immediate(MySignals::Ready); + self.as_mut().emit_immediate(MySignals::Ready); } - cpp.emit_queued(MySignals::DataChanged { + self.as_mut().emit_queued(MySignals::DataChanged { first: 1, second: QVariant::from_bool(true), third: QPoint::new(1, 2), diff --git a/cxx-qt-gen/test_inputs/types_qt_invokable.rs b/cxx-qt-gen/test_inputs/types_qt_invokable.rs index a693d1eb0..f1cc753fd 100644 --- a/cxx-qt-gen/test_inputs/types_qt_invokable.rs +++ b/cxx-qt-gen/test_inputs/types_qt_invokable.rs @@ -27,71 +27,67 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn test_color(&self, _cpp: &mut CppObj, color: &QColor) -> UniquePtr { + pub fn test_color(&self, color: &QColor) -> UniquePtr { color } #[qinvokable] - pub fn test_date(&self, _cpp: &mut CppObj, date: &QDate) -> QDate { + pub fn test_date(&self, date: &QDate) -> QDate { date } #[qinvokable] - pub fn test_date_time( - &self, - _cpp: &mut CppObj, - dateTime: &QDateTime, - ) -> UniquePtr { + pub fn test_date_time(&self, dateTime: &QDateTime) -> UniquePtr { dateTime } #[qinvokable] - pub fn test_point(&self, _cpp: &mut CppObj, point: &QPoint) -> QPoint { + pub fn test_point(&self, point: &QPoint) -> QPoint { point } #[qinvokable] - pub fn test_pointf(&self, _cpp: &mut CppObj, pointf: &QPointF) -> QPointF { + pub fn test_pointf(&self, pointf: &QPointF) -> QPointF { pointf } #[qinvokable] - pub fn test_rect(&self, _cpp: &mut CppObj, rect: &QRect) -> QRect { + pub fn test_rect(&self, rect: &QRect) -> QRect { rect } #[qinvokable] - pub fn test_rectf(&self, _cpp: &mut CppObj, rectf: &QRectF) -> QRectF { + pub fn test_rectf(&self, rectf: &QRectF) -> QRectF { rectf } #[qinvokable] - pub fn test_size(&self, _cpp: &mut CppObj, size: &QSize) -> QSize { + pub fn test_size(&self, size: &QSize) -> QSize { size } #[qinvokable] - pub fn test_sizef(&self, _cpp: &mut CppObj, sizef: &QSizeF) -> QSizeF { + pub fn test_sizef(&self, sizef: &QSizeF) -> QSizeF { sizef } #[qinvokable] - pub fn test_string(&self, _cpp: &mut CppObj, string: &QString) -> UniquePtr { + pub fn test_string(&self, string: &QString) -> UniquePtr { string.to_owned() } #[qinvokable] - pub fn test_time(&self, _cpp: &mut CppObj, time: &QTime) -> QTime { + pub fn test_time(&self, time: &QTime) -> QTime { time } #[qinvokable] - pub fn test_url(&self, _cpp: &mut CppObj, url: &QUrl) -> UniquePtr { + pub fn test_url(&self, url: &QUrl) -> UniquePtr { url } #[qinvokable] - pub fn test_variant(&self, _cpp: &mut CppObj, variant: &QVariant) -> UniquePtr { + pub fn test_variant(&self, variant: &QVariant) -> UniquePtr { variant } } diff --git a/cxx-qt-gen/test_outputs/custom_default.rs b/cxx-qt-gen/test_outputs/custom_default.rs index d060ecc1a..d16abce5d 100644 --- a/cxx-qt-gen/test_outputs/custom_default.rs +++ b/cxx-qt-gen/test_outputs/custom_default.rs @@ -52,31 +52,17 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + pub struct MyObject { private: i32, } impl MyObject {} - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn public(&self) -> i32 { - self.cpp.public() - } - - pub fn set_public(&mut self, value: i32) { - self.cpp.as_mut().set_public(value); - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_public(data.public); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_public(data.public); } } @@ -84,20 +70,14 @@ mod cxx_qt_ffi { public: i32, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { public: value.public().into(), } } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - impl Default for Data { fn default() -> Self { Self { public: 32 } @@ -114,8 +94,7 @@ mod cxx_qt_ffi { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/handlers.rs b/cxx-qt-gen/test_outputs/handlers.rs index f28a35ef8..07e7d516e 100644 --- a/cxx-qt-gen/test_outputs/handlers.rs +++ b/cxx-qt-gen/test_outputs/handlers.rs @@ -75,48 +75,21 @@ mod cxx_qt_ffi { use cxx_qt_lib::UpdateRequestHandler; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject { pub fn call_handle_update_request(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { - let mut cpp = CppObj::new(cpp); - self.handle_update_request(&mut cpp); + cpp.handle_update_request(); } } - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn number(&self) -> i32 { - self.cpp.number() - } - - pub fn set_number(&mut self, value: i32) { - self.cpp.as_mut().set_number(value); - } - - pub fn string(&self) -> &cxx_qt_lib::QString { - self.cpp.string() - } - - pub fn set_string(&mut self, value: &cxx_qt_lib::QString) { - self.cpp.as_mut().set_string(value); - } - - pub fn update_requester(&mut self) -> cxx_qt_lib::UpdateRequester { - cxx_qt_lib::UpdateRequester::from_unique_ptr(self.cpp.as_mut().update_requester()) - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_number(data.number); - self.set_string(&data.string); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_number(data.number); + self.as_mut().set_string(&data.string); } } @@ -126,8 +99,8 @@ mod cxx_qt_ffi { string: QString, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { number: value.number().into(), string: value.string().into(), @@ -135,14 +108,8 @@ mod cxx_qt_ffi { } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - - impl UpdateRequestHandler for MyObject { - fn handle_update_request(&mut self, _cpp: &mut CppObj) { + impl UpdateRequestHandler for MyObjectQt { + fn handle_update_request(self: Pin<&mut Self>) { println!("update") } } @@ -151,8 +118,7 @@ mod cxx_qt_ffi { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/invokables.cpp b/cxx-qt-gen/test_outputs/invokables.cpp index f019657b0..08216b050 100644 --- a/cxx-qt-gen/test_outputs/invokables.cpp +++ b/cxx-qt-gen/test_outputs/invokables.cpp @@ -28,28 +28,14 @@ void MyObject::invokable() { const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokable(); -} - -void -MyObject::invokableCppObj() -{ - const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableCppObjWrapper(*this); + m_rustObj->invokableWrapper(*this); } void MyObject::invokableMutable() { const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableMutable(); -} - -void -MyObject::invokableMutableCppObj() -{ - const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableMutableCppObjWrapper(*this); + m_rustObj->invokableMutableWrapper(*this); } void @@ -58,14 +44,7 @@ MyObject::invokableParameters(const QColor& opaque, qint32 primitive) { const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableParameters(opaque, trivial, primitive); -} - -void -MyObject::invokableParametersCppObj(qint32 primitive) -{ - const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableParametersCppObjWrapper(primitive, *this); + m_rustObj->invokableParametersWrapper(*this, opaque, trivial, primitive); } QColor @@ -73,7 +52,7 @@ MyObject::invokableReturnOpaque() { const std::lock_guard guard(m_rustObjMutex); return rust::cxxqtlib1::cxx_qt_convert>{}( - m_rustObj->invokableReturnOpaqueWrapper()); + m_rustObj->invokableReturnOpaqueWrapper(*this)); } qint32 @@ -81,7 +60,7 @@ MyObject::invokableReturnPrimitive() { const std::lock_guard guard(m_rustObjMutex); return rust::cxxqtlib1::cxx_qt_convert{}( - m_rustObj->invokableReturnPrimitive()); + m_rustObj->invokableReturnPrimitiveWrapper(*this)); } QString @@ -89,7 +68,7 @@ MyObject::invokableReturnStatic() { const std::lock_guard guard(m_rustObjMutex); return rust::cxxqtlib1::cxx_qt_convert>{}( - m_rustObj->invokableReturnStaticWrapper()); + m_rustObj->invokableReturnStaticWrapper(*this)); } } // namespace cxx_qt::my_object diff --git a/cxx-qt-gen/test_outputs/invokables.h b/cxx-qt-gen/test_outputs/invokables.h index 1eb93794d..bb399d168 100644 --- a/cxx-qt-gen/test_outputs/invokables.h +++ b/cxx-qt-gen/test_outputs/invokables.h @@ -23,13 +23,10 @@ class MyObject : public QObject public: Q_INVOKABLE void invokable(); - Q_INVOKABLE void invokableCppObj(); Q_INVOKABLE void invokableMutable(); - Q_INVOKABLE void invokableMutableCppObj(); Q_INVOKABLE void invokableParameters(const QColor& opaque, const QPoint& trivial, qint32 primitive); - Q_INVOKABLE void invokableParametersCppObj(qint32 primitive); Q_INVOKABLE QColor invokableReturnOpaque(); Q_INVOKABLE qint32 invokableReturnPrimitive(); Q_INVOKABLE QString invokableReturnStatic(); diff --git a/cxx-qt-gen/test_outputs/invokables.rs b/cxx-qt-gen/test_outputs/invokables.rs index 376bb7726..1af00a351 100644 --- a/cxx-qt-gen/test_outputs/invokables.rs +++ b/cxx-qt-gen/test_outputs/invokables.rs @@ -11,28 +11,33 @@ mod ffi { #[cxx_name = "MyObjectRust"] type MyObject; - #[cxx_name = "invokable"] - fn invokable(self: &MyObject); - #[cxx_name = "invokableCppObjWrapper"] - fn invokable_cpp_obj_wrapper(self: &MyObject, cpp: Pin<&mut MyObjectQt>); - #[cxx_name = "invokableMutable"] - fn invokable_mutable(self: &mut MyObject); - #[cxx_name = "invokableMutableCppObjWrapper"] - fn invokable_mutable_cpp_obj_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); - #[cxx_name = "invokableParameters"] - fn invokable_parameters(self: &MyObject, opaque: &QColor, trivial: &QPoint, primitive: i32); - #[cxx_name = "invokableParametersCppObjWrapper"] - fn invokable_parameters_cpp_obj_wrapper( + #[cxx_name = "invokableWrapper"] + fn invokable_wrapper(self: &MyObject, cpp: &MyObjectQt); + #[cxx_name = "invokableMutableWrapper"] + fn invokable_mutable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); + #[cxx_name = "invokableParametersWrapper"] + fn invokable_parameters_wrapper( self: &MyObject, + cpp: &MyObjectQt, + opaque: &QColor, + trivial: &QPoint, primitive: i32, - cpp: Pin<&mut MyObjectQt>, ); #[cxx_name = "invokableReturnOpaqueWrapper"] - fn invokable_return_opaque_wrapper(self: &mut MyObject) -> UniquePtr; - #[cxx_name = "invokableReturnPrimitive"] - fn invokable_return_primitive(self: &mut MyObject) -> i32; + fn invokable_return_opaque_wrapper( + self: &mut MyObject, + cpp: Pin<&mut MyObjectQt>, + ) -> UniquePtr; + #[cxx_name = "invokableReturnPrimitiveWrapper"] + fn invokable_return_primitive_wrapper( + self: &mut MyObject, + cpp: Pin<&mut MyObjectQt>, + ) -> i32; #[cxx_name = "invokableReturnStaticWrapper"] - fn invokable_return_static_wrapper(self: &mut MyObject) -> UniquePtr; + fn invokable_return_static_wrapper( + self: &mut MyObject, + cpp: Pin<&mut MyObjectQt>, + ) -> UniquePtr; } #[namespace = ""] @@ -78,50 +83,58 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject { - pub fn invokable_cpp_obj_wrapper(&self, cpp: std::pin::Pin<&mut FFICppObj>) { - let mut cpp = CppObj::new(cpp); - self.invokable_cpp_obj(&mut cpp); + pub fn invokable_wrapper(&self, cpp: &FFICppObj) { + cpp.invokable(); } - pub fn invokable_mutable_cpp_obj_wrapper(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { - let mut cpp = CppObj::new(cpp); - self.invokable_mutable_cpp_obj(&mut cpp); + pub fn invokable_mutable_wrapper(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { + cpp.invokable_mutable(); } - pub fn invokable_parameters_cpp_obj_wrapper( + pub fn invokable_parameters_wrapper( &self, + cpp: &FFICppObj, + opaque: &cxx_qt_lib::QColor, + trivial: &cxx_qt_lib::QPoint, primitive: i32, - cpp: std::pin::Pin<&mut FFICppObj>, ) { - let mut cpp = CppObj::new(cpp); - self.invokable_parameters_cpp_obj(primitive, &mut cpp); - } - - pub fn invokable_return_opaque_wrapper(&mut self) -> UniquePtr { - return self.invokable_return_opaque(); + cpp.invokable_parameters(opaque, trivial, primitive); } - pub fn invokable_return_static_wrapper(&mut self) -> UniquePtr { - return self.invokable_return_static(); + pub fn invokable_return_opaque_wrapper( + &mut self, + cpp: std::pin::Pin<&mut FFICppObj>, + ) -> UniquePtr { + return cpp.invokable_return_opaque(); } - pub fn invokable(&self) { - println!("invokable"); + pub fn invokable_return_primitive_wrapper( + &mut self, + cpp: std::pin::Pin<&mut FFICppObj>, + ) -> i32 { + return cpp.invokable_return_primitive(); } - pub fn invokable_cpp_obj(&self, cpp: &mut CppObj) { - println!("cppobj"); + pub fn invokable_return_static_wrapper( + &mut self, + cpp: std::pin::Pin<&mut FFICppObj>, + ) -> UniquePtr { + return cpp.invokable_return_static(); } + } - pub fn invokable_mutable(&mut self) { - println!("This method is mutable!"); + impl MyObjectQt { + pub fn invokable(&self) { + println!("invokable"); } - pub fn invokable_mutable_cpp_obj(&mut self, cpp: &mut CppObj) { + pub fn invokable_mutable(self: Pin<&mut Self>) { println!("This method is mutable!"); } @@ -134,19 +147,15 @@ mod cxx_qt_ffi { ); } - pub fn invokable_parameters_cpp_obj(&self, primitive: i32, cpp: &mut CppObj) { - println!("{}", primitive); - } - - pub fn invokable_return_opaque(&mut self) -> UniquePtr { + pub fn invokable_return_opaque(self: Pin<&mut Self>) -> UniquePtr { cxx_qt_lib::QColor::from_rgba(255, 0, 0, 0) } - pub fn invokable_return_primitive(&mut self) -> i32 { + pub fn invokable_return_primitive(self: Pin<&mut Self>) -> i32 { 2 } - pub fn invokable_return_static(&mut self) -> UniquePtr { + pub fn invokable_return_static(self: Pin<&mut Self>) -> UniquePtr { QString::from_str("static") } @@ -154,45 +163,25 @@ mod cxx_qt_ffi { println!("C++ context method"); } - pub fn cpp_context_method_mutable(&mut self) { + pub fn cpp_context_method_mutable(self: Pin<&mut Self>) { println!("mutable method"); } - pub fn cpp_context_method_cpp_obj(&mut self, cpp: &mut CppObj) { - println!("cppobj"); - } - pub fn cpp_context_method_return_opaque(&self) -> UniquePtr { cxx_qt_lib::QColor::from_rgba(255, 0, 0, 0) } - } - - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - pub fn grab_values_from_data(&mut self, mut data: Data) {} + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) {} } pub struct Data; - impl<'a> From<&CppObj<'a>> for Data { - fn from(_value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(_value: &MyObjectQt) -> Self { Self {} } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(_value: &mut CppObj<'a>) -> Self { - Self::from(&*_value) - } - } - impl MyObject { pub fn rust_only_method(&self) { println!("QML or C++ can't call this :)"); @@ -203,8 +192,7 @@ mod cxx_qt_ffi { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/naming.cpp b/cxx-qt-gen/test_outputs/naming.cpp index 25f545431..3891df39e 100644 --- a/cxx-qt-gen/test_outputs/naming.cpp +++ b/cxx-qt-gen/test_outputs/naming.cpp @@ -49,7 +49,7 @@ void MyObject::invokableName() { const std::lock_guard guard(m_rustObjMutex); - m_rustObj->invokableName(); + m_rustObj->invokableNameWrapper(*this); } namespace cxx_qt_my_object { diff --git a/cxx-qt-gen/test_outputs/naming.rs b/cxx-qt-gen/test_outputs/naming.rs index 01a7cb44b..25a7c91dc 100644 --- a/cxx-qt-gen/test_outputs/naming.rs +++ b/cxx-qt-gen/test_outputs/naming.rs @@ -16,8 +16,8 @@ mod ffi { #[cxx_name = "MyObjectRust"] type MyObject; - #[cxx_name = "invokableName"] - fn invokable_name(self: &MyObject); + #[cxx_name = "invokableNameWrapper"] + fn invokable_name_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); } unsafe extern "C++" { @@ -59,34 +59,25 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject { - pub fn invokable_name(&self) { - println!("Bye from Rust!"); + pub fn invokable_name_wrapper(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { + cpp.invokable_name(); } } - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn property_name(&self) -> i32 { - self.cpp.property_name() - } - - pub fn set_property_name(&mut self, value: i32) { - self.cpp.as_mut().set_property_name(value); + impl MyObjectQt { + pub fn invokable_name(self: Pin<&mut Self>) { + println!("Bye from Rust!"); + self.as_mut().set_property_name(5); } - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_property_name(data.property_name); + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_property_name(data.property_name); } } @@ -95,26 +86,19 @@ mod cxx_qt_ffi { property_name: i32, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { property_name: value.property_name().into(), } } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/passthrough.rs b/cxx-qt-gen/test_outputs/passthrough.rs index 288b965f5..bd6bc3294 100644 --- a/cxx-qt-gen/test_outputs/passthrough.rs +++ b/cxx-qt-gen/test_outputs/passthrough.rs @@ -111,30 +111,16 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject {} - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn number(&self) -> i32 { - self.cpp.number() - } - - pub fn set_number(&mut self, value: i32) { - self.cpp.as_mut().set_number(value); - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_number(data.number); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_number(data.number); } } @@ -143,20 +129,14 @@ mod cxx_qt_ffi { number: i32, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { number: value.number().into(), } } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - use super::MyTrait; impl MyTrait for Data { @@ -185,8 +165,7 @@ mod cxx_qt_ffi { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/properties.rs b/cxx-qt-gen/test_outputs/properties.rs index e9bcb165e..3bf22ef95 100644 --- a/cxx-qt-gen/test_outputs/properties.rs +++ b/cxx-qt-gen/test_outputs/properties.rs @@ -63,39 +63,17 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject {} - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn primitive(&self) -> i32 { - self.cpp.primitive() - } - - pub fn set_primitive(&mut self, value: i32) { - self.cpp.as_mut().set_primitive(value); - } - - pub fn opaque(&self) -> &cxx_qt_lib::QColor { - self.cpp.opaque() - } - - pub fn set_opaque(&mut self, value: &cxx_qt_lib::QColor) { - self.cpp.as_mut().set_opaque(value); - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_primitive(data.primitive); - self.set_opaque(data.opaque.as_ref().unwrap()); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_primitive(data.primitive); + self.as_mut().set_opaque(data.opaque.as_ref().unwrap()); } } @@ -105,8 +83,8 @@ mod cxx_qt_ffi { opaque: UniquePtr, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { primitive: value.primitive().into(), opaque: value.opaque().into(), @@ -114,18 +92,11 @@ mod cxx_qt_ffi { } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/signals.rs b/cxx-qt-gen/test_outputs/signals.rs index fa3d0375a..58e8ca106 100644 --- a/cxx-qt-gen/test_outputs/signals.rs +++ b/cxx-qt-gen/test_outputs/signals.rs @@ -27,7 +27,7 @@ mod ffi { type MyObject; #[cxx_name = "invokableWrapper"] - fn invokable_wrapper(self: &MyObject, cpp: Pin<&mut MyObjectQt>); + fn invokable_wrapper(self: &mut MyObject, cpp: Pin<&mut MyObjectQt>); } #[namespace = ""] @@ -72,6 +72,8 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + enum MySignals { Ready, DataChanged { @@ -85,79 +87,63 @@ mod cxx_qt_ffi { pub struct MyObject; impl MyObject { - pub fn invokable_wrapper(&self, cpp: std::pin::Pin<&mut FFICppObj>) { - let mut cpp = CppObj::new(cpp); - self.invokable(&mut cpp); + pub fn invokable_wrapper(&mut self, cpp: std::pin::Pin<&mut FFICppObj>) { + cpp.invokable(); } + } - pub fn invokable(&self, cpp: &mut CppObj) { + impl MyObjectQt { + pub fn invokable(self: Pin<&mut Self>) { unsafe { - cpp.emit_immediate(MySignals::Ready); + self.as_mut().emit_immediate(MySignals::Ready); } - cpp.emit_queued(MySignals::DataChanged { + self.as_mut().emit_queued(MySignals::DataChanged { first: 1, second: QVariant::from_bool(true), third: QPoint::new(1, 2), }); } - } - - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - pub fn emit_queued(&mut self, signal: MySignals) { + pub fn emit_queued(self: Pin<&mut Self>, signal: MySignals) { match signal { - MySignals::Ready {} => self.cpp.as_mut().emit_ready(), + MySignals::Ready {} => self.emit_ready(), MySignals::DataChanged { first, second, third, - } => self.cpp.as_mut().emit_data_changed(first, second, third), + } => self.emit_data_changed(first, second, third), } } - pub unsafe fn emit_immediate(&mut self, signal: MySignals) { + pub unsafe fn emit_immediate(self: Pin<&mut Self>, signal: MySignals) { match signal { - MySignals::Ready {} => self.cpp.as_mut().ready(), + MySignals::Ready {} => self.ready(), MySignals::DataChanged { first, second, third, - } => self.cpp.as_mut().data_changed(first, &second, &third), + } => self.data_changed(first, &second, &third), } } - pub fn grab_values_from_data(&mut self, mut data: Data) {} + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) {} } #[derive(Default)] pub struct Data; - impl<'a> From<&CppObj<'a>> for Data { - fn from(_value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(_value: &MyObjectQt) -> Self { Self {} } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(_value: &mut CppObj<'a>) -> Self { - Self::from(&*_value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/types_primitive_property.rs b/cxx-qt-gen/test_outputs/types_primitive_property.rs index f0ee73bdc..ad992ba84 100644 --- a/cxx-qt-gen/test_outputs/types_primitive_property.rs +++ b/cxx-qt-gen/test_outputs/types_primitive_property.rs @@ -92,102 +92,24 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject {} - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn boolean(&self) -> bool { - self.cpp.boolean() - } - - pub fn set_boolean(&mut self, value: bool) { - self.cpp.as_mut().set_boolean(value); - } - - pub fn float_32(&self) -> f32 { - self.cpp.float_32() - } - - pub fn set_float_32(&mut self, value: f32) { - self.cpp.as_mut().set_float_32(value); - } - - pub fn float_64(&self) -> f64 { - self.cpp.float_64() - } - - pub fn set_float_64(&mut self, value: f64) { - self.cpp.as_mut().set_float_64(value); - } - - pub fn int_8(&self) -> i8 { - self.cpp.int_8() - } - - pub fn set_int_8(&mut self, value: i8) { - self.cpp.as_mut().set_int_8(value); - } - - pub fn int_16(&self) -> i16 { - self.cpp.int_16() - } - - pub fn set_int_16(&mut self, value: i16) { - self.cpp.as_mut().set_int_16(value); - } - - pub fn int_32(&self) -> i32 { - self.cpp.int_32() - } - - pub fn set_int_32(&mut self, value: i32) { - self.cpp.as_mut().set_int_32(value); - } - - pub fn uint_8(&self) -> u8 { - self.cpp.uint_8() - } - - pub fn set_uint_8(&mut self, value: u8) { - self.cpp.as_mut().set_uint_8(value); - } - - pub fn uint_16(&self) -> u16 { - self.cpp.uint_16() - } - - pub fn set_uint_16(&mut self, value: u16) { - self.cpp.as_mut().set_uint_16(value); - } - - pub fn uint_32(&self) -> u32 { - self.cpp.uint_32() - } - - pub fn set_uint_32(&mut self, value: u32) { - self.cpp.as_mut().set_uint_32(value); - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_boolean(data.boolean); - self.set_float_32(data.float_32); - self.set_float_64(data.float_64); - self.set_int_8(data.int_8); - self.set_int_16(data.int_16); - self.set_int_32(data.int_32); - self.set_uint_8(data.uint_8); - self.set_uint_16(data.uint_16); - self.set_uint_32(data.uint_32); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_boolean(data.boolean); + self.as_mut().set_float_32(data.float_32); + self.as_mut().set_float_64(data.float_64); + self.as_mut().set_int_8(data.int_8); + self.as_mut().set_int_16(data.int_16); + self.as_mut().set_int_32(data.int_32); + self.as_mut().set_uint_8(data.uint_8); + self.as_mut().set_uint_16(data.uint_16); + self.as_mut().set_uint_32(data.uint_32); } } @@ -204,8 +126,8 @@ mod cxx_qt_ffi { uint_32: u32, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { boolean: value.boolean().into(), float_32: value.float_32().into(), @@ -220,18 +142,11 @@ mod cxx_qt_ffi { } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/types_qt_invokable.rs b/cxx-qt-gen/test_outputs/types_qt_invokable.rs index 375a815b7..93702cfc5 100644 --- a/cxx-qt-gen/test_outputs/types_qt_invokable.rs +++ b/cxx-qt-gen/test_outputs/types_qt_invokable.rs @@ -14,75 +14,55 @@ mod ffi { #[cxx_name = "testColorWrapper"] fn test_color_wrapper( self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, + cpp: &MyObjectQt, color: &QColor, ) -> UniquePtr; #[cxx_name = "testDateWrapper"] - fn test_date_wrapper(self: &MyObject, _cpp: Pin<&mut MyObjectQt>, date: &QDate) -> QDate; + fn test_date_wrapper(self: &MyObject, cpp: &MyObjectQt, date: &QDate) -> QDate; #[cxx_name = "testDateTimeWrapper"] fn test_date_time_wrapper( self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, + cpp: &MyObjectQt, dateTime: &QDateTime, ) -> UniquePtr; #[cxx_name = "testPointWrapper"] - fn test_point_wrapper( - self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, - point: &QPoint, - ) -> QPoint; + fn test_point_wrapper(self: &MyObject, cpp: &MyObjectQt, point: &QPoint) -> QPoint; #[cxx_name = "testPointfWrapper"] - fn test_pointf_wrapper( - self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, - pointf: &QPointF, - ) -> QPointF; + fn test_pointf_wrapper(self: &MyObject, cpp: &MyObjectQt, pointf: &QPointF) -> QPointF; #[cxx_name = "testRectWrapper"] - fn test_rect_wrapper(self: &MyObject, _cpp: Pin<&mut MyObjectQt>, rect: &QRect) -> QRect; + fn test_rect_wrapper(self: &MyObject, cpp: &MyObjectQt, rect: &QRect) -> QRect; #[cxx_name = "testRectfWrapper"] - fn test_rectf_wrapper( - self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, - rectf: &QRectF, - ) -> QRectF; + fn test_rectf_wrapper(self: &MyObject, cpp: &MyObjectQt, rectf: &QRectF) -> QRectF; #[cxx_name = "testSizeWrapper"] - fn test_size_wrapper(self: &MyObject, _cpp: Pin<&mut MyObjectQt>, size: &QSize) -> QSize; + fn test_size_wrapper(self: &MyObject, cpp: &MyObjectQt, size: &QSize) -> QSize; #[cxx_name = "testSizefWrapper"] - fn test_sizef_wrapper( - self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, - sizef: &QSizeF, - ) -> QSizeF; + fn test_sizef_wrapper(self: &MyObject, cpp: &MyObjectQt, sizef: &QSizeF) -> QSizeF; #[cxx_name = "testStringWrapper"] fn test_string_wrapper( self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, + cpp: &MyObjectQt, string: &QString, ) -> UniquePtr; #[cxx_name = "testTimeWrapper"] - fn test_time_wrapper(self: &MyObject, _cpp: Pin<&mut MyObjectQt>, time: &QTime) -> QTime; + fn test_time_wrapper(self: &MyObject, cpp: &MyObjectQt, time: &QTime) -> QTime; #[cxx_name = "testUrlWrapper"] - fn test_url_wrapper( - self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, - url: &QUrl, - ) -> UniquePtr; + fn test_url_wrapper(self: &MyObject, cpp: &MyObjectQt, url: &QUrl) -> UniquePtr; #[cxx_name = "testVariantWrapper"] fn test_variant_wrapper( self: &MyObject, - _cpp: Pin<&mut MyObjectQt>, + cpp: &MyObjectQt, variant: &QVariant, ) -> UniquePtr; } @@ -140,217 +120,187 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject { pub fn test_color_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, color: &cxx_qt_lib::QColor, ) -> UniquePtr { - let mut _cpp = CppObj::new(_cpp); - return self.test_color(&mut _cpp, color); + return cpp.test_color(color); } pub fn test_date_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, date: &cxx_qt_lib::QDate, ) -> cxx_qt_lib::QDate { - let mut _cpp = CppObj::new(_cpp); - return self.test_date(&mut _cpp, date); + return cpp.test_date(date); } pub fn test_date_time_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, dateTime: &cxx_qt_lib::QDateTime, ) -> UniquePtr { - let mut _cpp = CppObj::new(_cpp); - return self.test_date_time(&mut _cpp, dateTime); + return cpp.test_date_time(dateTime); } pub fn test_point_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, point: &cxx_qt_lib::QPoint, ) -> cxx_qt_lib::QPoint { - let mut _cpp = CppObj::new(_cpp); - return self.test_point(&mut _cpp, point); + return cpp.test_point(point); } pub fn test_pointf_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, pointf: &cxx_qt_lib::QPointF, ) -> cxx_qt_lib::QPointF { - let mut _cpp = CppObj::new(_cpp); - return self.test_pointf(&mut _cpp, pointf); + return cpp.test_pointf(pointf); } pub fn test_rect_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, rect: &cxx_qt_lib::QRect, ) -> cxx_qt_lib::QRect { - let mut _cpp = CppObj::new(_cpp); - return self.test_rect(&mut _cpp, rect); + return cpp.test_rect(rect); } pub fn test_rectf_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, rectf: &cxx_qt_lib::QRectF, ) -> cxx_qt_lib::QRectF { - let mut _cpp = CppObj::new(_cpp); - return self.test_rectf(&mut _cpp, rectf); + return cpp.test_rectf(rectf); } pub fn test_size_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, size: &cxx_qt_lib::QSize, ) -> cxx_qt_lib::QSize { - let mut _cpp = CppObj::new(_cpp); - return self.test_size(&mut _cpp, size); + return cpp.test_size(size); } pub fn test_sizef_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, sizef: &cxx_qt_lib::QSizeF, ) -> cxx_qt_lib::QSizeF { - let mut _cpp = CppObj::new(_cpp); - return self.test_sizef(&mut _cpp, sizef); + return cpp.test_sizef(sizef); } pub fn test_string_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, string: &cxx_qt_lib::QString, ) -> UniquePtr { - let mut _cpp = CppObj::new(_cpp); - return self.test_string(&mut _cpp, string); + return cpp.test_string(string); } pub fn test_time_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, time: &cxx_qt_lib::QTime, ) -> cxx_qt_lib::QTime { - let mut _cpp = CppObj::new(_cpp); - return self.test_time(&mut _cpp, time); + return cpp.test_time(time); } pub fn test_url_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, url: &cxx_qt_lib::QUrl, ) -> UniquePtr { - let mut _cpp = CppObj::new(_cpp); - return self.test_url(&mut _cpp, url); + return cpp.test_url(url); } pub fn test_variant_wrapper( &self, - _cpp: std::pin::Pin<&mut FFICppObj>, + cpp: &FFICppObj, variant: &cxx_qt_lib::QVariant, ) -> UniquePtr { - let mut _cpp = CppObj::new(_cpp); - return self.test_variant(&mut _cpp, variant); + return cpp.test_variant(variant); } + } - pub fn test_color(&self, _cpp: &mut CppObj, color: &QColor) -> UniquePtr { + impl MyObjectQt { + pub fn test_color(&self, color: &QColor) -> UniquePtr { color } - pub fn test_date(&self, _cpp: &mut CppObj, date: &QDate) -> QDate { + pub fn test_date(&self, date: &QDate) -> QDate { date } - pub fn test_date_time( - &self, - _cpp: &mut CppObj, - dateTime: &QDateTime, - ) -> UniquePtr { + pub fn test_date_time(&self, dateTime: &QDateTime) -> UniquePtr { dateTime } - pub fn test_point(&self, _cpp: &mut CppObj, point: &QPoint) -> QPoint { + pub fn test_point(&self, point: &QPoint) -> QPoint { point } - pub fn test_pointf(&self, _cpp: &mut CppObj, pointf: &QPointF) -> QPointF { + pub fn test_pointf(&self, pointf: &QPointF) -> QPointF { pointf } - pub fn test_rect(&self, _cpp: &mut CppObj, rect: &QRect) -> QRect { + pub fn test_rect(&self, rect: &QRect) -> QRect { rect } - pub fn test_rectf(&self, _cpp: &mut CppObj, rectf: &QRectF) -> QRectF { + pub fn test_rectf(&self, rectf: &QRectF) -> QRectF { rectf } - pub fn test_size(&self, _cpp: &mut CppObj, size: &QSize) -> QSize { + pub fn test_size(&self, size: &QSize) -> QSize { size } - pub fn test_sizef(&self, _cpp: &mut CppObj, sizef: &QSizeF) -> QSizeF { + pub fn test_sizef(&self, sizef: &QSizeF) -> QSizeF { sizef } - pub fn test_string(&self, _cpp: &mut CppObj, string: &QString) -> UniquePtr { + pub fn test_string(&self, string: &QString) -> UniquePtr { string.to_owned() } - pub fn test_time(&self, _cpp: &mut CppObj, time: &QTime) -> QTime { + pub fn test_time(&self, time: &QTime) -> QTime { time } - pub fn test_url(&self, _cpp: &mut CppObj, url: &QUrl) -> UniquePtr { + pub fn test_url(&self, url: &QUrl) -> UniquePtr { url } - pub fn test_variant(&self, _cpp: &mut CppObj, variant: &QVariant) -> UniquePtr { + pub fn test_variant(&self, variant: &QVariant) -> UniquePtr { variant } - } - - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - pub fn grab_values_from_data(&mut self, mut data: Data) {} + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) {} } #[derive(Default)] pub struct Data; - impl<'a> From<&CppObj<'a>> for Data { - fn from(_value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(_value: &MyObjectQt) -> Self { Self {} } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(_value: &mut CppObj<'a>) -> Self { - Self::from(&*_value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-gen/test_outputs/types_qt_property.rs b/cxx-qt-gen/test_outputs/types_qt_property.rs index bc6fbb47b..c29d871ab 100644 --- a/cxx-qt-gen/test_outputs/types_qt_property.rs +++ b/cxx-qt-gen/test_outputs/types_qt_property.rs @@ -130,138 +130,29 @@ mod cxx_qt_ffi { pub type FFICppObj = super::ffi::MyObjectQt; type UniquePtr = cxx::UniquePtr; + use std::pin::Pin; + #[derive(Default)] pub struct MyObject; impl MyObject {} - pub struct CppObj<'a> { - cpp: std::pin::Pin<&'a mut FFICppObj>, - } - - impl<'a> CppObj<'a> { - pub fn new(cpp: std::pin::Pin<&'a mut FFICppObj>) -> Self { - Self { cpp } - } - - pub fn color(&self) -> &cxx_qt_lib::QColor { - self.cpp.color() - } - - pub fn set_color(&mut self, value: &cxx_qt_lib::QColor) { - self.cpp.as_mut().set_color(value); - } - - pub fn date(&self) -> &cxx_qt_lib::QDate { - self.cpp.date() - } - - pub fn set_date(&mut self, value: &cxx_qt_lib::QDate) { - self.cpp.as_mut().set_date(value); - } - - pub fn date_time(&self) -> &cxx_qt_lib::QDateTime { - self.cpp.date_time() - } - - pub fn set_date_time(&mut self, value: &cxx_qt_lib::QDateTime) { - self.cpp.as_mut().set_date_time(value); - } - - pub fn point(&self) -> &cxx_qt_lib::QPoint { - self.cpp.point() - } - - pub fn set_point(&mut self, value: &cxx_qt_lib::QPoint) { - self.cpp.as_mut().set_point(value); - } - - pub fn pointf(&self) -> &cxx_qt_lib::QPointF { - self.cpp.pointf() - } - - pub fn set_pointf(&mut self, value: &cxx_qt_lib::QPointF) { - self.cpp.as_mut().set_pointf(value); - } - - pub fn rect(&self) -> &cxx_qt_lib::QRect { - self.cpp.rect() - } - - pub fn set_rect(&mut self, value: &cxx_qt_lib::QRect) { - self.cpp.as_mut().set_rect(value); - } - - pub fn rectf(&self) -> &cxx_qt_lib::QRectF { - self.cpp.rectf() - } - - pub fn set_rectf(&mut self, value: &cxx_qt_lib::QRectF) { - self.cpp.as_mut().set_rectf(value); - } - - pub fn size(&self) -> &cxx_qt_lib::QSize { - self.cpp.size() - } - - pub fn set_size(&mut self, value: &cxx_qt_lib::QSize) { - self.cpp.as_mut().set_size(value); - } - - pub fn sizef(&self) -> &cxx_qt_lib::QSizeF { - self.cpp.sizef() - } - - pub fn set_sizef(&mut self, value: &cxx_qt_lib::QSizeF) { - self.cpp.as_mut().set_sizef(value); - } - - pub fn string(&self) -> &cxx_qt_lib::QString { - self.cpp.string() - } - - pub fn set_string(&mut self, value: &cxx_qt_lib::QString) { - self.cpp.as_mut().set_string(value); - } - - pub fn time(&self) -> &cxx_qt_lib::QTime { - self.cpp.time() - } - - pub fn set_time(&mut self, value: &cxx_qt_lib::QTime) { - self.cpp.as_mut().set_time(value); - } - - pub fn url(&self) -> &cxx_qt_lib::QUrl { - self.cpp.url() - } - - pub fn set_url(&mut self, value: &cxx_qt_lib::QUrl) { - self.cpp.as_mut().set_url(value); - } - - pub fn variant(&self) -> &cxx_qt_lib::QVariant { - self.cpp.variant() - } - - pub fn set_variant(&mut self, value: &cxx_qt_lib::QVariant) { - self.cpp.as_mut().set_variant(value); - } - - pub fn grab_values_from_data(&mut self, mut data: Data) { - self.set_color(data.color.as_ref().unwrap()); - self.set_date(&data.date); - self.set_date_time(data.date_time.as_ref().unwrap()); - self.set_point(&data.point); - self.set_pointf(&data.pointf); - self.set_rect(&data.rect); - self.set_rectf(&data.rectf); - self.set_size(&data.size); - self.set_sizef(&data.sizef); - self.set_string(data.string.as_ref().unwrap()); - self.set_time(&data.time); - self.set_url(data.url.as_ref().unwrap()); - self.set_variant(data.variant.as_ref().unwrap()); + impl MyObjectQt { + pub fn grab_values_from_data(mut self: Pin<&mut Self>, mut data: Data) { + self.as_mut().set_color(data.color.as_ref().unwrap()); + self.as_mut().set_date(&data.date); + self.as_mut() + .set_date_time(data.date_time.as_ref().unwrap()); + self.as_mut().set_point(&data.point); + self.as_mut().set_pointf(&data.pointf); + self.as_mut().set_rect(&data.rect); + self.as_mut().set_rectf(&data.rectf); + self.as_mut().set_size(&data.size); + self.as_mut().set_sizef(&data.sizef); + self.as_mut().set_string(data.string.as_ref().unwrap()); + self.as_mut().set_time(&data.time); + self.as_mut().set_url(data.url.as_ref().unwrap()); + self.as_mut().set_variant(data.variant.as_ref().unwrap()); } } @@ -282,8 +173,8 @@ mod cxx_qt_ffi { variant: UniquePtr, } - impl<'a> From<&CppObj<'a>> for Data { - fn from(value: &CppObj<'a>) -> Self { + impl From<&MyObjectQt> for Data { + fn from(value: &MyObjectQt) -> Self { Self { color: value.color().into(), date: value.date().into(), @@ -302,18 +193,11 @@ mod cxx_qt_ffi { } } - impl<'a> From<&mut CppObj<'a>> for Data { - fn from(value: &mut CppObj<'a>) -> Self { - Self::from(&*value) - } - } - pub fn create_rs() -> std::boxed::Box { std::default::Default::default() } - pub fn initialise_cpp(cpp: std::pin::Pin<&mut FFICppObj>) { - let mut wrapper = CppObj::new(cpp); - wrapper.grab_values_from_data(Data::default()); + pub fn initialise_cpp(cpp: std::pin::Pin<&mut MyObjectQt>) { + cpp.grab_values_from_data(Data::default()); } } diff --git a/cxx-qt-lib/src/lib.rs b/cxx-qt-lib/src/lib.rs index 69bcf43f4..d11d3a1da 100644 --- a/cxx-qt-lib/src/lib.rs +++ b/cxx-qt-lib/src/lib.rs @@ -7,6 +7,8 @@ mod types; pub use types::*; -pub trait UpdateRequestHandler { - fn handle_update_request(&mut self, cpp: &mut C); +use std::pin::Pin; + +pub trait UpdateRequestHandler { + fn handle_update_request(self: Pin<&mut Self>); } diff --git a/examples/demo_threading/src/lib.rs b/examples/demo_threading/src/lib.rs index 132bb5aa5..09335c353 100644 --- a/examples/demo_threading/src/lib.rs +++ b/examples/demo_threading/src/lib.rs @@ -219,8 +219,8 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn start_server(&mut self, cpp: &mut CppObj) { - if self.join_handles.is_some() { + pub fn start_server(mut self: Pin<&mut Self>) { + if self.rust().join_handles.is_some() { println!("Already running a server!"); return; } @@ -264,9 +264,9 @@ mod ffi { // Prepare our update thread // // When values change this then requests an update to Qt - let qt_tx = self.qt_tx.clone(); + let qt_tx = self.rust().qt_tx.clone(); let update_network_tx = network_tx.clone(); - let update_requester = cpp.update_requester(); + let update_requester = self.as_mut().update_requester(); let update_sensors_changed = sensors_changed.clone(); let run_update = async move { loop { @@ -360,23 +360,25 @@ mod ffi { }; // Start our threads - self.join_handles = Some([ - std::thread::spawn(move || block_on(run_timeout)), - std::thread::spawn(move || block_on(run_update)), - std::thread::spawn(move || block_on(run_sensors)), - std::thread::spawn(move || block_on(run_server)), - ]); + unsafe { + self.rust_mut().join_handles = Some([ + std::thread::spawn(move || block_on(run_timeout)), + std::thread::spawn(move || block_on(run_update)), + std::thread::spawn(move || block_on(run_sensors)), + std::thread::spawn(move || block_on(run_server)), + ]); + } } } - impl UpdateRequestHandler> for EnergyUsage { - fn handle_update_request(&mut self, cpp: &mut CppObj) { + impl UpdateRequestHandler for cxx_qt::QObject { + fn handle_update_request(self: Pin<&mut Self>) { // Process the new data from the background thread - if let Some(data) = self.qt_rx.try_iter().last() { + if let Some(data) = self.rust().qt_rx.try_iter().last() { // Here we have constructed a new Data struct so can consume it's values // for other uses we could have passed an Enum across the channel // and then process the required action here - cpp.grab_values_from_data(data); + self.grab_values_from_data(data); } } } diff --git a/examples/qml_extension_plugin/core/src/lib.rs b/examples/qml_extension_plugin/core/src/lib.rs index da899f205..eb1fe0269 100644 --- a/examples/qml_extension_plugin/core/src/lib.rs +++ b/examples/qml_extension_plugin/core/src/lib.rs @@ -63,29 +63,30 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn increment(&self, cpp: &mut CppObj) { - cpp.set_number(cpp.number() + 1); + pub fn increment(self: Pin<&mut Self>) { + let new_number = self.number() + 1; + self.set_number(new_number); } #[qinvokable] - pub fn reset(&self, cpp: &mut CppObj) { + pub fn reset(self: Pin<&mut Self>) { let data: DataSerde = serde_json::from_str(DEFAULT_STR).unwrap(); - cpp.grab_values_from_data(data.into()); + self.grab_values_from_data(data.into()); } #[qinvokable] - pub fn serialize(&self, cpp: &mut CppObj) -> UniquePtr { - let data = Data::from(cpp); + pub fn serialize(&self) -> UniquePtr { + let data = Data::from(self); let data_serde = DataSerde::from(data); let data_string = serde_json::to_string(&data_serde).unwrap(); QString::from_str(&data_string) } #[qinvokable] - pub fn grab_values(&self, cpp: &mut CppObj) { + pub fn grab_values(self: Pin<&mut Self>) { let string = r#"{"number": 2, "string": "Goodbye!"}"#; let data: DataSerde = serde_json::from_str(string).unwrap(); - cpp.grab_values_from_data(data.into()); + self.grab_values_from_data(data.into()); } } } diff --git a/examples/qml_features/src/lib.rs b/examples/qml_features/src/lib.rs index 531ff3e2a..fa48601a2 100644 --- a/examples/qml_features/src/lib.rs +++ b/examples/qml_features/src/lib.rs @@ -40,9 +40,9 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn increment_number_self(&self, cpp: &mut CppObj) { - let value = cpp.number() + 1; - cpp.set_number(value); + pub fn increment_number_self(self: Pin<&mut Self>) { + let value = self.as_ref().number() + 1; + self.set_number(value); } #[qinvokable] diff --git a/examples/qml_features/src/mock_qt_types.rs b/examples/qml_features/src/mock_qt_types.rs index 2cc33d601..2dd52b36d 100644 --- a/examples/qml_features/src/mock_qt_types.rs +++ b/examples/qml_features/src/mock_qt_types.rs @@ -76,26 +76,26 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn test_signal(&self, cpp: &mut CppObj) { - cpp.emit_queued(Signal::Ready); - cpp.emit_queued(Signal::DataChanged { + pub fn test_signal(mut self: Pin<&mut Self>) { + self.as_mut().emit_queued(Signal::Ready); + self.as_mut().emit_queued(Signal::DataChanged { variant: QVariant::from(true), }); } #[qinvokable] - pub fn test_unsafe_signal(&self, cpp: &mut CppObj) { + pub fn test_unsafe_signal(mut self: Pin<&mut Self>) { unsafe { - cpp.emit_immediate(Signal::Ready); - cpp.emit_immediate(Signal::DataChanged { + self.as_mut().emit_immediate(Signal::Ready); + self.as_mut().emit_immediate(Signal::DataChanged { variant: QVariant::from(true), }); } } #[qinvokable] - pub fn test_color_property(&self, cpp: &mut CppObj) { - cpp.set_color(QColor::from_rgba(0, 0, 255, 255).as_ref().unwrap()); + pub fn test_color_property(self: Pin<&mut Self>) { + self.set_color(QColor::from_rgba(0, 0, 255, 255).as_ref().unwrap()); } #[qinvokable] @@ -104,10 +104,10 @@ mod ffi { } #[qinvokable] - pub fn test_date_property(&self, cpp: &mut CppObj) { - let mut date = *cpp.date(); + pub fn test_date_property(self: Pin<&mut Self>) { + let mut date = *self.date(); date.set_date(2021, 12, 31); - cpp.set_date(&date); + self.set_date(&date); } #[qinvokable] @@ -118,8 +118,8 @@ mod ffi { } #[qinvokable] - pub fn test_date_time_property(&self, cpp: &mut CppObj) { - let date_time = cpp.date_time(); + pub fn test_date_time_property(self: Pin<&mut Self>) { + let date_time = self.date_time(); let new_date_time = QDateTime::from_date_and_time( &QDate::new(2021, 12, 31), &QTime::new( @@ -129,7 +129,7 @@ mod ffi { date_time.time().msec() * 5, ), ); - cpp.set_date_time(new_date_time.as_ref().unwrap()); + self.set_date_time(new_date_time.as_ref().unwrap()); } #[qinvokable] @@ -146,11 +146,11 @@ mod ffi { } #[qinvokable] - pub fn test_point_property(&self, cpp: &mut CppObj) { - let mut point = *cpp.point(); + pub fn test_point_property(self: Pin<&mut Self>) { + let mut point = *self.point(); point.set_x(point.x() * 2); point.set_y(point.y() * 3); - cpp.set_point(&point); + self.set_point(&point); } #[qinvokable] @@ -162,11 +162,11 @@ mod ffi { } #[qinvokable] - pub fn test_pointf_property(&self, cpp: &mut CppObj) { - let mut point = *cpp.pointf(); + pub fn test_pointf_property(self: Pin<&mut Self>) { + let mut point = *self.pointf(); point.set_x(point.x() * 2.0); point.set_y(point.y() * 3.0); - cpp.set_pointf(&point); + self.set_pointf(&point); } #[qinvokable] @@ -178,15 +178,15 @@ mod ffi { } #[qinvokable] - pub fn test_rect_property(&self, cpp: &mut CppObj) { - let mut rect = *cpp.rect(); + pub fn test_rect_property(self: Pin<&mut Self>) { + let mut rect = *self.rect(); // Copy width and height, otherwise when we adjust the x and y it affects the width and height let (width, height) = (rect.width(), rect.height()); rect.set_x(rect.x() * 2); rect.set_y(rect.y() * 3); rect.set_width(width * 4); rect.set_height(height * 5); - cpp.set_rect(&rect); + self.set_rect(&rect); } #[qinvokable] @@ -202,15 +202,15 @@ mod ffi { } #[qinvokable] - pub fn test_rectf_property(&self, cpp: &mut CppObj) { - let mut rect = *cpp.rectf(); + pub fn test_rectf_property(self: Pin<&mut Self>) { + let mut rect = *self.rectf(); // Copy width and height, otherwise when we adjust the x and y it affects the width and height let (width, height) = (rect.width(), rect.height()); rect.set_x(rect.x() * 2.0); rect.set_y(rect.y() * 3.0); rect.set_width(width * 4.0); rect.set_height(height * 5.0); - cpp.set_rectf(&rect); + self.set_rectf(&rect); } #[qinvokable] @@ -226,11 +226,11 @@ mod ffi { } #[qinvokable] - pub fn test_size_property(&self, cpp: &mut CppObj) { - let mut size = *cpp.size(); + pub fn test_size_property(self: Pin<&mut Self>) { + let mut size = *self.size(); size.set_width(size.width() * 2); size.set_height(size.height() * 3); - cpp.set_size(&size); + self.set_size(&size); } #[qinvokable] @@ -242,11 +242,11 @@ mod ffi { } #[qinvokable] - pub fn test_sizef_property(&self, cpp: &mut CppObj) { - let mut size = *cpp.sizef(); + pub fn test_sizef_property(self: Pin<&mut Self>) { + let mut size = *self.sizef(); size.set_width(size.width() * 2.0); size.set_height(size.height() * 3.0); - cpp.set_sizef(&size); + self.set_sizef(&size); } #[qinvokable] @@ -258,9 +258,9 @@ mod ffi { } #[qinvokable] - pub fn test_string_property(&self, cpp: &mut CppObj) { - let string = QString::from_str(&(cpp.string().to_string() + "/cxx-qt")); - cpp.set_string(string.as_ref().unwrap()); + pub fn test_string_property(self: Pin<&mut Self>) { + let string = QString::from_str(&(self.string().to_string() + "/cxx-qt")); + self.set_string(string.as_ref().unwrap()); } #[qinvokable] @@ -269,15 +269,15 @@ mod ffi { } #[qinvokable] - pub fn test_time_property(&self, cpp: &mut CppObj) { - let mut time = *cpp.time(); + pub fn test_time_property(self: Pin<&mut Self>) { + let mut time = *self.time(); time.set_hms( time.hour() * 2, time.minute() * 3, time.second() * 4, time.msec() * 5, ); - cpp.set_time(&time); + self.set_time(&time); } #[qinvokable] @@ -293,9 +293,9 @@ mod ffi { } #[qinvokable] - pub fn test_url_property(&self, cpp: &mut CppObj) { - let url = QUrl::from_str(&(cpp.url().string() + "/cxx-qt")); - cpp.set_url(url.as_ref().unwrap()); + pub fn test_url_property(self: Pin<&mut Self>) { + let url = QUrl::from_str(&(self.url().string() + "/cxx-qt")); + self.set_url(url.as_ref().unwrap()); } #[qinvokable] @@ -304,14 +304,26 @@ mod ffi { } #[qinvokable] - pub fn test_variant_property(&self, cpp: &mut CppObj) { - match cpp.variant().value() { - QVariantValue::Bool(b) => cpp.set_variant(QVariant::from(!b).as_ref().unwrap()), - QVariantValue::F32(f) => cpp.set_variant(QVariant::from(f * 2.0).as_ref().unwrap()), - QVariantValue::F64(d) => cpp.set_variant(QVariant::from(d * 2.0).as_ref().unwrap()), - QVariantValue::I8(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), - QVariantValue::I16(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), - QVariantValue::I32(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), + pub fn test_variant_property(mut self: Pin<&mut Self>) { + match self.variant().value() { + QVariantValue::Bool(b) => self + .as_mut() + .set_variant(QVariant::from(!b).as_ref().unwrap()), + QVariantValue::F32(f) => self + .as_mut() + .set_variant(QVariant::from(f * 2.0).as_ref().unwrap()), + QVariantValue::F64(d) => self + .as_mut() + .set_variant(QVariant::from(d * 2.0).as_ref().unwrap()), + QVariantValue::I8(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), + QVariantValue::I16(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), + QVariantValue::I32(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), QVariantValue::QColor(mut color) => { if let Some(mut color) = color.as_mut() { color.as_mut().set_red(0); @@ -319,11 +331,13 @@ mod ffi { color.as_mut().set_blue(255); color.as_mut().set_alpha(255); } - cpp.set_variant(QVariant::from(color.as_ref().unwrap()).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(color.as_ref().unwrap()).as_ref().unwrap()); } QVariantValue::QDate(mut date) => { date.set_date(2021, 12, 31); - cpp.set_variant(QVariant::from(date).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(date).as_ref().unwrap()); } QVariantValue::QDateTime(mut date_time) => { if let Some(mut date_time) = date_time.as_mut() { @@ -336,28 +350,28 @@ mod ffi { ); date_time.as_mut().set_time(new_time); } - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(date_time.as_ref().unwrap()) .as_ref() .unwrap(), ); } QVariantValue::QPoint(point) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QPoint::new(point.x() * 2, point.y() * 2)) .as_ref() .unwrap(), ); } QVariantValue::QPointF(pointf) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QPointF::new(pointf.x() * 2.0, pointf.y() * 2.0)) .as_ref() .unwrap(), ); } QVariantValue::QRect(rect) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QRect::new( rect.x() * 2, rect.y() * 3, @@ -369,7 +383,7 @@ mod ffi { ); } QVariantValue::QRectF(rectf) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QRectF::new( rectf.x() * 2.0, rectf.y() * 3.0, @@ -381,14 +395,14 @@ mod ffi { ); } QVariantValue::QSize(size) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QSize::new(size.width() * 2, size.height() * 2)) .as_ref() .unwrap(), ); } QVariantValue::QSizeF(sizef) => { - cpp.set_variant( + self.as_mut().set_variant( QVariant::from(QSizeF::new(sizef.width() * 2.0, sizef.height() * 2.0)) .as_ref() .unwrap(), @@ -396,7 +410,8 @@ mod ffi { } QVariantValue::QString(string) => { let string = QString::from_str(&(string.to_string() + "/cxx-qt")); - cpp.set_variant(QVariant::from(string.as_ref().unwrap()).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(string.as_ref().unwrap()).as_ref().unwrap()); } QVariantValue::QTime(mut time) => { time.set_hms( @@ -405,15 +420,23 @@ mod ffi { time.second() * 4, time.msec() * 5, ); - cpp.set_variant(QVariant::from(time).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(time).as_ref().unwrap()); } QVariantValue::QUrl(url) => { let url = QUrl::from_str(&(url.string() + "/cxx-qt")); - cpp.set_variant(QVariant::from(url.as_ref().unwrap()).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(url.as_ref().unwrap()).as_ref().unwrap()); } - QVariantValue::U8(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), - QVariantValue::U16(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), - QVariantValue::U32(i) => cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()), + QVariantValue::U8(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), + QVariantValue::U16(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), + QVariantValue::U32(i) => self + .as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()), _ => panic!("Incorrect variant type!"), } } diff --git a/examples/qml_features/src/rust_obj_invokables.rs b/examples/qml_features/src/rust_obj_invokables.rs index 72eb4d11d..bb01a8bff 100644 --- a/examples/qml_features/src/rust_obj_invokables.rs +++ b/examples/qml_features/src/rust_obj_invokables.rs @@ -25,20 +25,23 @@ pub mod ffi { impl cxx_qt::QObject { // ANCHOR: book_cpp_obj #[qinvokable] - pub fn invokable_mutate_cpp(&self, cpp: &mut CppObj) { - cpp.set_number(cpp.number() * 2); + pub fn invokable_mutate_cpp(self: Pin<&mut Self>) { + let new_number = self.number() * 2; + self.set_number(new_number); } // ANCHOR_END: book_cpp_obj #[qinvokable] pub fn invokable_return(&self) -> i32 { - self.rust_only_field + self.rust().rust_only_field } #[qinvokable] - pub fn invokable_multiply(&mut self, factor: i32) -> i32 { - self.rust_only_method(factor); - self.rust_only_field + pub fn invokable_multiply(mut self: Pin<&mut Self>, factor: i32) -> i32 { + unsafe { + self.as_mut().rust_mut().rust_only_method(factor); + } + self.rust().rust_only_field } } diff --git a/examples/qml_features/src/serialisation.rs b/examples/qml_features/src/serialisation.rs index f6eaf1ad5..dcb5ec83d 100644 --- a/examples/qml_features/src/serialisation.rs +++ b/examples/qml_features/src/serialisation.rs @@ -60,8 +60,8 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn as_json_str(&self, cpp: &mut CppObj) -> UniquePtr { - let data = Data::from(cpp); + pub fn as_json_str(&self) -> UniquePtr { + let data = Data::from(self); let data_serde = DataSerde::from(data); let data_string = serde_json::to_string(&data_serde).unwrap(); QString::from_str(&data_string) @@ -69,10 +69,10 @@ mod ffi { // ANCHOR: book_grab_values #[qinvokable] - pub fn grab_values(&self, cpp: &mut CppObj) { + pub fn grab_values(self: Pin<&mut Self>) { let string = r#"{"number": 2, "string": "Goodbye!"}"#; let data_serde: DataSerde = serde_json::from_str(string).unwrap(); - cpp.grab_values_from_data(data_serde.into()); + self.grab_values_from_data(data_serde.into()); } // ANCHOR_END: book_grab_values } diff --git a/examples/qml_features/src/signals.rs b/examples/qml_features/src/signals.rs index e9a907b6c..d83600af4 100644 --- a/examples/qml_features/src/signals.rs +++ b/examples/qml_features/src/signals.rs @@ -45,18 +45,21 @@ pub mod ffi { // ANCHOR: book_rust_obj_impl impl cxx_qt::QObject { #[qinvokable] - pub fn invokable(&self, cpp: &mut CppObj) { + pub fn invokable(mut self: Pin<&mut Self>) { unsafe { - cpp.emit_immediate(Signal::Ready); + self.as_mut().emit_immediate(Signal::Ready); } - cpp.emit_queued(Signal::RustDataChanged { data: cpp.data() }); - cpp.emit_queued(Signal::TrivialDataChanged { - trivial: *cpp.trivial(), - }); - cpp.emit_queued(Signal::OpaqueDataChanged { - opaque: QVariant::from_ref(cpp.opaque()), - }); + let signal = Signal::RustDataChanged { data: self.data() }; + self.as_mut().emit_queued(signal); + let signal = Signal::TrivialDataChanged { + trivial: *self.trivial(), + }; + self.as_mut().emit_queued(signal); + let signal = Signal::OpaqueDataChanged { + opaque: QVariant::from_ref(self.opaque()), + }; + self.as_mut().emit_queued(signal); } } // ANCHOR_END: book_rust_obj_impl diff --git a/examples/qml_features/src/types.rs b/examples/qml_features/src/types.rs index 2795d333d..eb719fd19 100644 --- a/examples/qml_features/src/types.rs +++ b/examples/qml_features/src/types.rs @@ -31,13 +31,15 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn test_variant_property(&self, cpp: &mut CppObj) { - match cpp.variant().value() { + pub fn test_variant_property(mut self: Pin<&mut Self>) { + match self.variant().value() { QVariantValue::Bool(b) => { - cpp.set_variant(QVariant::from(!b).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(!b).as_ref().unwrap()); } QVariantValue::I32(i) => { - cpp.set_variant(QVariant::from(i * 2).as_ref().unwrap()); + self.as_mut() + .set_variant(QVariant::from(i * 2).as_ref().unwrap()); } _ => panic!("Incorrect variant type!"), } diff --git a/examples/qml_minimal/src/lib.rs b/examples/qml_minimal/src/lib.rs index 658701a23..f64859b56 100644 --- a/examples/qml_minimal/src/lib.rs +++ b/examples/qml_minimal/src/lib.rs @@ -42,8 +42,9 @@ mod ffi { // ANCHOR: book_rustobj_impl impl cxx_qt::QObject { #[qinvokable] - pub fn increment_number(&self, cpp: &mut CppObj) { - cpp.set_number(cpp.number() + 1); + pub fn increment_number(self: Pin<&mut Self>) { + let previous = self.as_ref().number(); + self.set_number(previous + 1); } #[qinvokable] diff --git a/examples/qml_with_threaded_logic/src/lib.rs b/examples/qml_with_threaded_logic/src/lib.rs index 22e892f6f..9a914a374 100644 --- a/examples/qml_with_threaded_logic/src/lib.rs +++ b/examples/qml_with_threaded_logic/src/lib.rs @@ -68,31 +68,35 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn change_url(&self, cpp: &mut CppObj) { - let url = cpp.url().to_string(); + pub fn change_url(self: Pin<&mut Self>) { + let url = self.as_ref().url().to_string(); let new_url = if url == "known" { "unknown" } else { "known" }; - cpp.set_url(QString::from_str(new_url).as_ref().unwrap()); + self.set_url(QString::from_str(new_url).as_ref().unwrap()); } #[qinvokable] - pub fn refresh_title(&self, cpp: &mut CppObj) { + pub fn refresh_title(mut self: Pin<&mut Self>) { // TODO: SeqCst is probably not the most efficient solution - let new_load = - self.loading - .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst); + let new_load = self.rust().loading.compare_exchange( + false, + true, + Ordering::SeqCst, + Ordering::SeqCst, + ); if new_load.is_err() { println!("Skipped refresh_title request, because already in progress."); return; } - cpp.set_title(QString::from_str("Loading...").as_ref().unwrap()); + self.as_mut() + .set_title(QString::from_str("Loading...").as_ref().unwrap()); - let url = cpp.url().to_string(); + let url = self.as_ref().url().to_string(); // ANCHOR: book_cpp_update_requester // Retrieve the update requester from the CppObj - let update_requester = cpp.update_requester(); + let update_requester = self.as_mut().update_requester(); // ANCHOR_END: book_cpp_update_requester - let event_sender = self.event_sender.clone(); + let event_sender = self.rust().event_sender.clone(); let fetch_title = async move { // Simulate the delay of a network request with a simple timer @@ -116,31 +120,34 @@ mod ffi { } #[qinvokable] - pub fn new_title_value(&mut self) { + pub fn new_title_value(self: Pin<&mut Self>) { println!("title changed"); } #[qinvokable] - pub fn new_url_value(&mut self, cpp: &mut CppObj) { - self.refresh_title(cpp); + pub fn new_url_value(self: Pin<&mut Self>) { + self.refresh_title(); } - fn process_event(&mut self, event: &Event, cpp: &mut CppObj) { + fn process_event(mut self: Pin<&mut Self>, event: &Event) { match event { Event::TitleArrived(title) => { - cpp.set_title(QString::from_str(title).as_ref().unwrap()); - self.loading.store(false, Ordering::Relaxed); + self.as_mut() + .set_title(QString::from_str(title).as_ref().unwrap()); + self.rust().loading.store(false, Ordering::Relaxed); } } } } // ANCHOR: book_update_request_handler - impl UpdateRequestHandler> for Website { - fn handle_update_request(&mut self, cpp: &mut CppObj) { - while let Some(event) = self.event_queue.next().now_or_never() { + impl UpdateRequestHandler for cxx_qt::QObject { + fn handle_update_request(mut self: Pin<&mut Self>) { + while let Some(event) = + unsafe { self.as_mut().rust_mut().event_queue.next().now_or_never() } + { if let Some(event) = event { - self.process_event(&event, cpp); + self.as_mut().process_event(&event); } } } diff --git a/tests/basic_cxx_qt/src/data.rs b/tests/basic_cxx_qt/src/data.rs index 4c3488079..cbf10aa75 100644 --- a/tests/basic_cxx_qt/src/data.rs +++ b/tests/basic_cxx_qt/src/data.rs @@ -60,18 +60,18 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn as_json_str(&self, cpp: &mut CppObj) -> UniquePtr { - let data = Data::from(cpp); + pub fn as_json_str(&self) -> UniquePtr { + let data = Data::from(self); let data_serde = DataSerde::from(data); let data_string = serde_json::to_string(&data_serde).unwrap(); QString::from_str(&data_string) } #[qinvokable] - pub fn grab_values(&self, cpp: &mut CppObj) { + pub fn grab_values(self: Pin<&mut Self>) { let string = r#"{"number": 2, "string": "Goodbye!"}"#; let data_serde: DataSerde = serde_json::from_str(string).unwrap(); - cpp.grab_values_from_data(data_serde.into()); + self.grab_values_from_data(data_serde.into()); } } } diff --git a/tests/basic_cxx_qt/src/lib.rs b/tests/basic_cxx_qt/src/lib.rs index b6d4d8038..0bc02f88b 100644 --- a/tests/basic_cxx_qt/src/lib.rs +++ b/tests/basic_cxx_qt/src/lib.rs @@ -37,9 +37,9 @@ mod ffi { impl cxx_qt::QObject { #[qinvokable] - pub fn double_number_self(&self, cpp: &mut CppObj) { - let value = cpp.number() * 2; - cpp.set_number(value); + pub fn double_number_self(self: Pin<&mut Self>) { + let value = self.number() * 2; + self.set_number(value); } #[qinvokable] @@ -56,20 +56,20 @@ mod ffi { } #[qinvokable] - pub fn request_update_test(&self, cpp: &mut CppObj) { - let update_requester = cpp.update_requester(); + pub fn request_update_test(self: Pin<&mut Self>) { + let update_requester = self.update_requester(); update_requester.request_update(); } #[qinvokable] - pub fn request_update_test_multi_thread(&self, cpp: &mut CppObj) { + pub fn request_update_test_multi_thread(mut self: Pin<&mut Self>) { static N_THREADS: usize = 100; static N_REQUESTS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); let mut handles = Vec::new(); for _ in 0..N_THREADS { - let update_requester = cpp.update_requester(); + let update_requester = self.as_mut().update_requester(); handles.push(std::thread::spawn(move || { update_requester.request_update(); N_REQUESTS.fetch_add(1, std::sync::atomic::Ordering::Relaxed); @@ -89,13 +89,15 @@ mod ffi { #[qinvokable] pub fn update_call_count(&self) -> i32 { - self.update_call_count + self.rust().update_call_count } } - impl UpdateRequestHandler> for MyObject { - fn handle_update_request(&mut self, _cpp: &mut CppObj) { - self.update_call_count += 1; + impl UpdateRequestHandler for cxx_qt::QObject { + fn handle_update_request(self: Pin<&mut Self>) { + unsafe { + self.rust_mut().update_call_count += 1; + } } } }