Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cxx-qt-gen: remove support for cxx_type and cxx_return_type #554

Merged
merged 3 commits into from
May 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Always call `qt_build_utils::setup_linker()` in `CxxQtBuilder` and remove the proxy method
- Moved to `syn` 2.0 internally and for any exported `syn` types

### Removed

- Removed support for `cxx_type` and `cxx_return_type` and related conversion methods.

## [0.5.3](https://github.com/KDAB/cxx-qt/compare/v0.5.2...v0.5.3) - 2023-05-19

### Fixed
Expand Down
1 change: 0 additions & 1 deletion book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ SPDX-License-Identifier: MIT OR Apache-2.0
- [Bridge](./concepts/bridge.md)
- [Qt](./concepts/qt.md)
- [Types](./concepts/types.md)
- [Type Conversions](./concepts/type-conversions.md)
- [Build Systems](./concepts/build_systems.md)
- [Threading](./concepts/threading.md)
- [Nested Objects](./concepts/nested_objects.md)
Expand Down
66 changes: 0 additions & 66 deletions book/src/concepts/type-conversions.md

This file was deleted.

46 changes: 0 additions & 46 deletions book/src/concepts/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,49 +67,3 @@ To use a custom type with `QVariant` implement the `QVariantValue` trait for you
A full example of implementing a custom struct with `QVariant` is shown in the [qml_features types example](https://github.com/KDAB/cxx-qt/blob/main/examples/qml_features/rust/src/types.rs).

Also any custom types or alias in C++ should be registered with Qt using `qRegisterMetaType<T>("TYPE")` to ensure that they work with QML.

## Opaque Type Conversions

If your type can't be marked as trivial for CXX, but the Qt API needs to take the type by value (eg `T` rather than `const T&` or `::std::unique_ptr<T>`),
then you can define [type conversions](type-conversions.md) in C++ that convert between pointers / references and values.
Then when using properties, invokables, or signals an attribute in the macro can be used.

### Properties

In the following example using `cxx_type` means that `OpaqueExampleType` will be the type of the `Q_PROPERTY`, getter, and setter in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the type and CXX-Qt will perform the conversions between.

```rust,ignore
#[cxx_qt::qobject]
struct MyStruct {
#[qproperty(cxx_type = "OpaqueExampleType")]
my_property: cxx::UniquePtr<OpaqueExampleType>
}
```

### Invokables

In the following example using `return_cxx_type` means that `OpaqueExampleType` will be the return type of the `Q_INVOKABLE` in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the return type and CXX-Qt will perform the conversion between.

```rust,ignore
impl qobject::MyStruct {
#[qinvokable(return_cxx_type = "OpaqueExampleType")]
pub fn invokable(&self) -> cxx::UniquePtr<OpaqueExampleType> {
...
}
}
```

### Signals

In the following example using `cxx_type` means that `OpaqueExampleType` will be the parameter type of the `Q_SIGNAL` in C++.
On the Rust side `cxx::UniquePtr<OpaqueExampleType>` will be the type in the enum and CXX-Qt will perform the conversion between.

```rust,ignore
#[cxx_qt::qsignals(MyStruct)]
pub enum Signals {
#[cxx_type = "OpaqueExampleType"]
NewData { value: cxx::UniquePtr<OpaqueExampleType> },
}
```
21 changes: 0 additions & 21 deletions book/src/qobject/qobject_struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,27 +93,6 @@ These setters and getters assure that the changed signal is emitted every time t
Any field that's not marked as `#[qproperty]` won't be accessible from C++, but it will be accessible from Rust.
See the [Private fields section](#private-methods-and-fields)

### `cxx_type`

You can change the C++ type that your property uses by adding the `cxx_type` attribute to the `#[qproperty]` macro.

This is especially useful if your property type is an opaque C++ type and can't be owned directly by Rust.
Then it might be necessary to wrap it in a [cxx::UniquePtr](https://docs.rs/cxx/latest/cxx/struct.UniquePtr.html).

However, you may still want your `Q_PROPERTY` to use the opaque type directly.
This can easily be achieved by using `cxx_type`.

``` rust,ignore,noplayground
#[cxx_qt::qobject]
struct MyStruct {
#[qproperty(cxx_type="OpaqueExampleType")]
my_property: cxx::UniquePtr<OpaqueExampleType>
}
```
In this case, CXX-Qt will automatically convert the `::std::unique_ptr<OpaqueExampleType>` to `OpaqueExampleType`.

For details, see the [page on type conversions](../concepts/type-conversions.md).

## Default

The [`Default` trait](https://doc.rust-lang.org/std/default/trait.Default.html) needs to be implemented for the `#[cxx_qt::qobject]` marked struct either by hand or by using the derive macro `#[derive(Default)]`.
Expand Down
4 changes: 1 addition & 3 deletions crates/cxx-qt-gen/src/generator/cpp/inherit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ pub fn generate(

for method in inherited_methods {
let return_type = if let ReturnType::Type(_, ty) = &method.method.sig.output {
CppType::from(ty, &None, cxx_mappings)?
.as_cxx_ty()
.to_owned()
CppType::from(ty, cxx_mappings)?.as_cxx_ty().to_owned()
} else {
"void".to_owned()
};
Expand Down
50 changes: 18 additions & 32 deletions crates/cxx-qt-gen/src/generator/cpp/invokable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
fragment::{CppFragment, CppNamedType},
qobject::GeneratedCppQObjectBlocks,
types::CppType,
CXX_QT_CONVERT, RUST_OBJ_MUTEX_LOCK_GUARD,
RUST_OBJ_MUTEX_LOCK_GUARD,
},
naming::{invokable::QInvokableName, qobject::QObjectName},
},
Expand All @@ -30,8 +30,8 @@ pub fn generate_cpp_invokables(
let qobject_ident = qobject_idents.cpp_class.cpp.to_string();
for invokable in invokables {
let idents = QInvokableName::from(invokable);
let cxx_ty = if let ReturnType::Type(_, ty) = &invokable.method.sig.output {
Some(CppType::from(ty, &invokable.return_cxx_type, cxx_mappings)?)
let return_cxx_ty = if let ReturnType::Type(_, ty) = &invokable.method.sig.output {
Some(CppType::from(ty, cxx_mappings)?)
} else {
None
};
Expand All @@ -56,7 +56,7 @@ pub fn generate_cpp_invokables(
} else {
Ok(Some(CppNamedType {
ident: ident.to_string(),
ty: CppType::from(ty, &None, cxx_mappings)?,
ty: CppType::from(ty, cxx_mappings)?,
}))
}
} else {
Expand Down Expand Up @@ -90,9 +90,9 @@ pub fn generate_cpp_invokables(

generated.methods.push(CppFragment::Pair {
header: format!(
"Q_INVOKABLE {is_virtual}{cxx_ty} {ident}({parameter_types}){is_const}{is_final}{is_override};",
cxx_ty = if let Some(cxx_ty) = &cxx_ty {
cxx_ty.as_cxx_ty()
"Q_INVOKABLE {is_virtual}{return_cxx_ty} {ident}({parameter_types}){is_const}{is_final}{is_override};",
return_cxx_ty = if let Some(return_cxx_ty) = &return_cxx_ty {
return_cxx_ty.as_cxx_ty()
} else {
"void"
},
Expand All @@ -116,15 +116,15 @@ pub fn generate_cpp_invokables(
),
source: formatdoc! {
r#"
{cxx_ty}
{return_cxx_ty}
{qobject_ident}::{ident}({parameter_types}){is_const}
{{
{rust_obj_guard}
{body};
}}
"#,
cxx_ty = if let Some(cxx_ty) = &cxx_ty {
cxx_ty.as_cxx_ty()
return_cxx_ty = if let Some(return_cxx_ty) = &return_cxx_ty {
return_cxx_ty.as_cxx_ty()
} else {
"void"
},
Expand All @@ -133,13 +133,8 @@ pub fn generate_cpp_invokables(
parameter_types = parameter_types,
qobject_ident = qobject_ident,
rust_obj_guard = RUST_OBJ_MUTEX_LOCK_GUARD,
body = if let Some(cxx_ty) = &cxx_ty {
format!("return {convert}<{cxx_ty}, {rust_ty}>{{}}({body})",
convert = CXX_QT_CONVERT,
cxx_ty = cxx_ty.as_cxx_ty(),
rust_ty = cxx_ty.as_rust_ty(),
body = body
)
body = if return_cxx_ty.is_some() {
format!("return {body}", body = body)
} else {
body
},
Expand Down Expand Up @@ -169,7 +164,6 @@ mod tests {
method: parse_quote! { fn void_invokable(&self) {} },
mutable: false,
parameters: vec![],
return_cxx_type: None,
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -178,9 +172,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -189,9 +181,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { &QColor },
cxx_type: None,
}],
return_cxx_type: Some("QColor".to_owned()),
specifiers: HashSet::new(),
},
ParsedQInvokable {
Expand All @@ -200,9 +190,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: {
let mut specifiers = HashSet::new();
specifiers.insert(ParsedQInvokableSpecifiers::Final);
Expand Down Expand Up @@ -255,7 +243,7 @@ mod tests {
MyObject::trivialInvokable(::std::int32_t param) const
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<::std::int32_t, ::std::int32_t>{}(m_rustObj->trivialInvokableWrapper(*this, param));
return m_rustObj->trivialInvokableWrapper(*this, param);
}
"#}
);
Expand All @@ -267,16 +255,16 @@ mod tests {
};
assert_str_eq!(
header,
"Q_INVOKABLE QColor opaqueInvokable(QColor const& param);"
"Q_INVOKABLE ::std::unique_ptr<QColor> opaqueInvokable(QColor const& param);"
);
assert_str_eq!(
source,
indoc! {r#"
QColor
::std::unique_ptr<QColor>
MyObject::opaqueInvokable(QColor const& param)
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<QColor, ::std::unique_ptr<QColor>>{}(m_rustObj->opaqueInvokableWrapper(*this, param));
return m_rustObj->opaqueInvokableWrapper(*this, param);
}
"#}
);
Expand All @@ -297,7 +285,7 @@ mod tests {
MyObject::specifiersInvokable(::std::int32_t param) const
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<::std::int32_t, ::std::int32_t>{}(m_rustObj->specifiersInvokableWrapper(*this, param));
return m_rustObj->specifiersInvokableWrapper(*this, param);
}
"#}
);
Expand All @@ -311,9 +299,7 @@ mod tests {
parameters: vec![ParsedFunctionParameter {
ident: format_ident!("param"),
ty: parse_quote! { i32 },
cxx_type: None,
}],
return_cxx_type: None,
specifiers: HashSet::new(),
}];
let qobject_idents = create_qobjectname();
Expand Down Expand Up @@ -345,7 +331,7 @@ mod tests {
MyObject::trivialInvokable(A1 param) const
{
const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);
return ::rust::cxxqtlib1::cxx_qt_convert<B2, B2>{}(m_rustObj->trivialInvokableWrapper(*this, param));
return m_rustObj->trivialInvokableWrapper(*this, param);
}
"#}
);
Expand Down
1 change: 0 additions & 1 deletion crates/cxx-qt-gen/src/generator/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use syn::Result;

pub const RUST_OBJ_MUTEX_LOCK_GUARD: &str =
"const ::std::lock_guard<::std::recursive_mutex> guard(*m_rustObjMutex);";
pub const CXX_QT_CONVERT: &str = "::rust::cxxqtlib1::cxx_qt_convert";

/// Representation of the generated C++ code for a group of QObjects
pub struct GeneratedCppBlocks {
Expand Down
14 changes: 6 additions & 8 deletions crates/cxx-qt-gen/src/generator/cpp/property/getter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,31 @@
// SPDX-License-Identifier: MIT OR Apache-2.0

use crate::generator::{
cpp::{fragment::CppFragment, types::CppType, CXX_QT_CONVERT, RUST_OBJ_MUTEX_LOCK_GUARD},
cpp::{fragment::CppFragment, types::CppType, RUST_OBJ_MUTEX_LOCK_GUARD},
naming::property::QPropertyName,
};
use indoc::formatdoc;

pub fn generate(idents: &QPropertyName, qobject_ident: &str, cxx_ty: &CppType) -> CppFragment {
CppFragment::Pair {
header: format!(
"{cxx_ty} const& {ident_getter}() const;",
cxx_ty = cxx_ty.as_cxx_ty(),
"{return_cxx_ty} const& {ident_getter}() const;",
return_cxx_ty = cxx_ty.as_cxx_ty(),
ident_getter = idents.getter.cpp
),
source: formatdoc!(
r#"
{cxx_ty} const&
{return_cxx_ty} const&
{qobject_ident}::{ident_getter}() const
{{
{rust_obj_guard}
return {convert}<{cxx_ty} const&, {rust_ty} const&>{{}}(m_rustObj->{ident_getter}(*this));
return m_rustObj->{ident_getter}(*this);
}}
"#,
convert = CXX_QT_CONVERT,
cxx_ty = cxx_ty.as_cxx_ty(),
return_cxx_ty = cxx_ty.as_cxx_ty(),
ident_getter = idents.getter.cpp.to_string(),
qobject_ident = qobject_ident,
rust_obj_guard = RUST_OBJ_MUTEX_LOCK_GUARD,
rust_ty = cxx_ty.as_rust_ty(),
),
}
}
Loading