当前位置: 首页 > news >正文

【CXX-Qt】2.4 嵌套对象

Rust Qt 对象可以作为属性或参数相互嵌套。

嵌套对象通过指向其 QObject 表示的指针来引用。

首先,在桥接模块的 extern 块中正常定义一个类型。

extern "RustQt" {
    #[qobject]
    #[qml_element]
    #[qproperty(i32, counter)]
    type InnerObject = super::InnerObjectRust;
}

然后,可以通过使用 *mut T 将其作为属性、可调用方法的参数或信号参数使用。如下例所示,将 InnerObject 嵌套到 OuterObject 中。

需要使用 C++ CXX 类型作为 `T` 类型,而不是 Rust 结构体。
要访问嵌套对象的可变可调用方法和属性设置器,需要将 `*mut T` 转换为 `Pin<&mut T>`。
#[cxx_qt::bridge]
pub mod qobject {
    extern "RustQt" {
        #[qobject]
        #[qml_element]
        #[qproperty(i32, counter)]
        type InnerObject = super::InnerObjectRust;
    }

    extern "RustQt" {
        /// 一个信号,展示如何将另一个 QObject 作为参数引用
        ///
        /// # 安全性
        ///
        /// 由于使用了裸指针,这在 CXX 中被视为不安全
        #[qsignal]
        unsafe fn called(self: Pin<&mut InnerObject>, inner: *mut InnerObject);
    }

    extern "RustQt" {
        #[qobject]
        #[qml_element]
        #[qproperty(*mut InnerObject, inner)]
        type OuterObject = super::OuterObjectRust;

        /// 一个信号,展示如何将另一个 QObject 作为参数引用
        ///
        /// # 安全性
        ///
        /// 由于使用了裸指针,这在 CXX 中被视为不安全
        #[qsignal]
        unsafe fn called(self: Pin<&mut OuterObject>, inner: *mut InnerObject);
    }

    unsafe extern "RustQt" {
        /// 打印给定内部 QObject 的计数
        ///
        /// # 安全性
        ///
        /// 由于在公共方法中解引用指针,这需要标记为不安全
        #[qinvokable]
        #[cxx_name = "printCount"]
        unsafe fn print_count(self: Pin<&mut OuterObject>, inner: *mut InnerObject);

        /// 重置存储在 Q_PROPERTY 中的内部 QObject 的计数器
        #[qinvokable]
        fn reset(self: Pin<&mut OuterObject>);
    }

    impl cxx_qt::Constructor<()> for OuterObject {}
}

use core::pin::Pin;

/// 内部 QObject
#[derive(Default)]
pub struct InnerObjectRust {
    counter: i32,
}

/// 外部 QObject,具有指向内部 QObject 的 Q_PROPERTY
pub struct OuterObjectRust {
    inner: *mut qobject::InnerObject,
}

impl Default for OuterObjectRust {
    fn default() -> Self {
        Self {
            inner: std::ptr::null_mut(),
        }
    }
}

impl qobject::OuterObject {
    /// 打印给定内部 QObject 的计数
    ///
    /// # 安全性
    ///
    /// 由于在公共方法中解引用指针,这需要标记为不安全
    pub unsafe fn print_count(self: Pin<&mut Self>, inner: *mut qobject::InnerObject) {
        if let Some(inner) = inner.as_ref() {
            println!("内部对象的计数器属性: {}", inner.counter());
        }

        self.called(inner);
    }

    /// 重置存储在 Q_PROPERTY 中的内部 QObject 的计数器
    pub fn reset(self: Pin<&mut Self>) {
        // 需要将 *mut T 转换为 Pin<&mut T>,以便访问方法
        if let Some(inner) = unsafe { self.inner().as_mut() } {
            let pinned_inner = unsafe { Pin::new_unchecked(inner) };
            // 现在可以像平常一样使用 pinned_inner
            pinned_inner.set_counter(10);
        }

        // 获取 *mut T
        let inner = *self.inner();
        unsafe { self.called(inner) };
    }
}

impl cxx_qt::Initialize for qobject::OuterObject {
    /// 初始化 QObject,将一个信号连接到另一个信号
    fn initialize(self: core::pin::Pin<&mut Self>) {
        // 示例:将一个 QObject 的信号连接到另一个 QObject 的信号
        // 这将触发 OuterObject::Called 以触发 InnerObject::Called
        self.on_called(|qobject, obj| {
            // 需要将 *mut T 转换为 Pin<&mut T>,以便访问方法
            if let Some(inner) = unsafe { qobject.inner().as_mut() } {
                let pinned_inner = unsafe { Pin::new_unchecked(inner) };
                // 现在可以像平常一样使用 pinned_inner
                unsafe {
                    pinned_inner.called(obj);
                }
            }
        })
        .release();
    }
}
http://www.dtcms.com/a/83428.html

相关文章:

  • allWebPlugin中间件自动安装升级
  • mybatis操作数据库报错Cause: Cannot find class: ${com.mysql.cj.jdbc.Driver}
  • 六十天前端强化训练之第二十六天之Vue Router 动态路由参数大师级详解
  • Qt下集成大华网络相机SDK示例开发
  • 大数据学习(76)-Impala计算引擎
  • 【Json-RPC框架】:Json存储结构,operator[ ]返回的就是对应的value对象
  • 根据MAC地址获取设备厂商
  • SOFABoot-06-健康检查
  • 7 合并两个有序列表
  • MediaPipe软件包如何构建和安装
  • Vue中组件和插件有什么区别?
  • Android 根据Url使用Retrofit框架进行文件下载
  • 数字内容体验优化用户参与路径
  • AI比人脑更强,因为被植入思维模型【15】马斯洛需求层次理论
  • 使用Python开发自动驾驶技术:车道线检测模型
  • Java的流程控制
  • 机器学习与数据分析相关数学基础知识总结
  • Redis 内存管理
  • Java中的多态
  • Java IO性能优化:字节流与缓冲流的对比与实战分析
  • Cache与虚拟存储:计算机系统中的“快取侠”与“空间魔术师”
  • 导出tdengine创建表语句
  • Java并发编程(1)
  • 【指针(2)-- 使用指针的技巧】
  • BBR 和 CUBIC 对长肥管道的不同反应
  • 使用请求调用本地部署的stable-diffusion接口
  • 从零开始实现 C++ TinyWebServer 处理请求 HttpRequest类详解
  • 3D引擎:Three.js有什么有什么优缺点?
  • 数据人的进阶之路:四年数仓实践与成长思考
  • Elasticsearch + Docker:实现容器化部署指南