Skip to content

Commit bf40f52

Browse files
Add book entry
1 parent 17a4112 commit bf40f52

File tree

4 files changed

+42
-14
lines changed

4 files changed

+42
-14
lines changed

book/src/bridge/attributes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ For [`#[qproperty]`](./extern_rustqt.md#properties), a CXX or Rust name can be p
4343
The `#[auto_cxx_name]` and `#[auto_rust_name]` attributes can be used to automatically rename cxx and rust names.
4444
These are placed at a block level on `extern "RustQt"` or `extern "C++Qt"` blocks, and will automatically case convert the items inside, unless they specify either a `rust_name` or `cxx_name`.
4545
By default `#[auto_cxx_name]` will generate a camelCase conversion for`cxx_name` and `#[auto_rust_name]` will generate a snake_case conversion for `rust_name`.
46+
47+
### Automatic wrapping
48+
49+
A fairly common operation is calling a method on the inner rust type, via the `.rust()` accessor. This can be simplified
50+
with the `#[auto_wrap]` attribute. This will generate a wrapper for your function which accesses the rust method of that name.

crates/cxx-qt-gen/src/generator/rust/method.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// SPDX-License-Identifier: MIT OR Apache-2.0
55

66
use crate::generator::rust::{get_call_params_tokens, get_params_tokens};
7+
use crate::naming::TypeNames;
78
use crate::{
89
generator::{naming::qobject::QObjectNames, rust::fragment::GeneratedRustFragment},
910
parser::method::ParsedMethod,
@@ -14,6 +15,7 @@ use syn::{parse_quote_spanned, spanned::Spanned, Result};
1415
pub fn generate_rust_methods(
1516
invokables: &[&ParsedMethod],
1617
qobject_names: &QObjectNames,
18+
type_names: &TypeNames,
1719
) -> Result<GeneratedRustFragment> {
1820
let cpp_class_name_rust = &qobject_names.name.rust_unqualified();
1921

@@ -56,18 +58,29 @@ pub fn generate_rust_methods(
5658
Some(quote! { unsafe })
5759
};
5860

61+
let method_safety = if invokable.safe {
62+
None
63+
} else {
64+
Some(quote! { unsafe })
65+
};
66+
67+
let qualified_impl = type_names.rust_qualified(&invokable.qobject_ident)?;
68+
5969
let wrapper_fn = if invokable.wrap {
6070
vec![parse_quote_spanned! {
6171
invokable.method.span() =>
62-
#unsafe_call fn #invokable_ident_rust(#parameter_signatures) #return_type {
63-
self.rust().#invokable_ident_rust(#call_parameters)
72+
#(#cfgs)*
73+
impl #qualified_impl {
74+
#method_safety fn #invokable_ident_rust(#parameter_signatures) #return_type {
75+
self.rust().#invokable_ident_rust(#call_parameters)
76+
}
6477
}
6578
}]
6679
} else {
6780
vec![]
6881
};
6982

70-
GeneratedRustFragment {
83+
Ok(GeneratedRustFragment {
7184
cxx_mod_contents: vec![parse_quote_spanned! {
7285
invokable.method.span() =>
7386
// Note: extern "Rust" block does not need to be unsafe
@@ -87,9 +100,9 @@ pub fn generate_rust_methods(
87100
}
88101
}],
89102
cxx_qt_mod_contents: wrapper_fn,
90-
}
103+
})
91104
})
92-
.collect::<Vec<_>>();
105+
.collect::<Result<Vec<_>>>()?;
93106

94107
Ok(GeneratedRustFragment::flatten(generated))
95108
}
@@ -130,8 +143,12 @@ mod tests {
130143
];
131144
let qobject_names = create_qobjectname();
132145

133-
let generated =
134-
generate_rust_methods(&invokables.iter().collect::<Vec<_>>(), &qobject_names).unwrap();
146+
let generated = generate_rust_methods(
147+
&invokables.iter().collect::<Vec<_>>(),
148+
&qobject_names,
149+
&TypeNames::mock(),
150+
)
151+
.unwrap();
135152

136153
assert_eq!(generated.cxx_mod_contents.len(), 4);
137154
assert_eq!(generated.cxx_qt_mod_contents.len(), 2);
@@ -175,8 +192,10 @@ mod tests {
175192
assert_tokens_eq(
176193
&generated.cxx_qt_mod_contents[0],
177194
quote! {
178-
fn opaque_invokable(self: Pin<&mut MyObject>, param: &QColor) -> UniquePtr<QColor> {
179-
self.rust().opaque_invokable(param)
195+
impl qobject::MyObject {
196+
fn opaque_invokable(self: Pin<&mut MyObject>, param: &QColor) -> UniquePtr<QColor> {
197+
self.rust().opaque_invokable(param)
198+
}
180199
}
181200
},
182201
);
@@ -196,8 +215,10 @@ mod tests {
196215
assert_tokens_eq(
197216
&generated.cxx_qt_mod_contents[1],
198217
quote! {
199-
unsafe fn unsafe_invokable(self:&MyObject, param: *mut T) -> *mut T {
200-
self.rust().unsafe_invokable(param)
218+
impl qobject::MyObject {
219+
unsafe fn unsafe_invokable(self:&MyObject, param: *mut T) -> *mut T {
220+
self.rust().unsafe_invokable(param)
221+
}
201222
}
202223
},
203224
);

crates/cxx-qt-gen/src/generator/rust/qobject.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl GeneratedRustFragment {
3535
type_names,
3636
structured_qobject,
3737
)?,
38-
generate_rust_methods(&structured_qobject.methods, &qobject_names)?,
38+
generate_rust_methods(&structured_qobject.methods, &qobject_names, type_names)?,
3939
inherit::generate(&qobject_names, &structured_qobject.inherited_methods)?,
4040
generate_rust_signals(&structured_qobject.signals, &qobject_names, type_names)?,
4141
];

crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,10 @@ cxx_qt::static_assertions::assert_eq_size!(
780780
cxx_qt::signalhandler::CxxQtSignalHandler<SecondObjectCxxQtSignalClosurepropertyNameChanged>,
781781
[usize; 2]
782782
);
783-
unsafe fn my_function(self: &SecondObject, param: i32) {
784-
self.rust().my_function(param)
783+
impl ffi::SecondObject {
784+
fn my_function(self: &SecondObject, param: i32) {
785+
self.rust().my_function(param)
786+
}
785787
}
786788
impl ffi::SecondObject {
787789
#[doc = "Connect the given function pointer to the signal "]

0 commit comments

Comments
 (0)