gpui-dotnet深入浅出1/2

大家好呀,我是搬砖工.上文感谢大家的热情关注和点赞支持.我马不停蹄的开始gpui-donet系列的第二篇文章.内容太长.计划按2节展开.

言归正传,我们开始今天的正文.我们先熟悉下项目结构.

项目结构

gpui-dotnet/
├── Directory.Build.props         # 全局 MSBuild 属性(版本/作者/许可等)
├── Gpui.slnx                     # 解决方案(.slnx 新格式)
├── LICENSE                       # MIT 许可
├── NOTICE                        # 第三方归属说明(Zed/GPUI 引用)
├── NUGET_README.md               # NuGet 包页 README
├── README.md                     # 项目主 README
├── dotnet-tools.json             # 本地 .NET 工具清单
│
├── bindings/
│   └── schema.json               # ★ 语义组件/操作 Schema(生成器的单一事实源)
│
├── include/
│   └── gpui_dotnet.h             # 公开 C 头文件(ABI v1 完整声明)
│
├── crates/
│   └── gpui-dotnet/              # ★ Rust 原生宿主库
│       ├── Cargo.toml            # crate 清单(依赖 pinned GPUI)
│       ├── Cargo.lock            # 锁文件
│       ├── build.rs              # csbindgen 生成 C# 绑定
│       └── src/                  # 见「第三节」
│
├── src/
│   ├── Gpui/                     # ★ 托管公共 API 与运行时源码
│   ├── Gpui.Core/                # 平台中立包项目(GPUI.NET.Core)
│   ├── Gpui.Native/              # RID 原生包项目(win/linux/osx)
│   └── Gpui.Generators/          # ★ Roslyn 源生成器
│
├── samples/
│   ├── Gpui.Sample/              # ★ 交互式组件画廊示例
│   └── Gpui.Bench/               # 基准测试
│
├── tests/
│   └── Gpui.Tests/               # ★ 托管契约与生成器测试
│
├── tools/
│   ├── Gpui.Bindings.Generator/  # ★ 语义绑定生成器(schema → C#/Rust)
│   └── uidrive/                  # Windows UI 驱动(点击/滚轮/截图)
│
└── docs/                         # 设计文档

项目结构清晰.层次划分很明确.通过封装gpui的Rust库.生成了gpui-dotnet的rs库,生成c约定的dll.同时生成c#的调用:
`csharpbiding

Rust和C#有明确的边界
提示:我们C#侧和Rust侧底色不一样.大家可以很快速区分功能实现在那一端.
再提示:我们第一次编译Sample,需要先编译rust版的dll.需要几分钟时间,请耐心等待一下.并没有出错

我们C#侧的项目依赖如下:

在这里插入图片描述
通过依赖SG生成器.我们自己的View可以生成被Rust调用的方法.上篇我们介绍过了.

接下来我们再来看整体架构

整体架构

整个框架围绕一条清晰的边界线展开:C# 拥有什么,Rust 拥有什么。跨边界的唯一通道是 C ABI,且只允许「状态转换 / 粗粒度批量」通过。记住这个批量.这个让我们和Rust的交互不用设置一次就调用一次.对性能有很大影响.

图 1 · 所有权边界:两侧通过 C ABI 通信,Rust 独占帧敏感状态
要特别关注下虚拟行的渲染.我们昨天已经演示过了.他的方法参数如下:

    [GpuiListItem]
    private Element ServiceRow(int index, ref RenderContext ui)
    {
    ...//根据index获取u
    return ui.Button(
         "service-row",
         ui.HStack(
                 ui.TableCell(
                     0,
                     ui.Text($"{u.Id}")
                         .FontSize(Px(theme.Typography.BodySmall))
                         .TextColor(colors.Text)
                 ),
    	).ItemsCenter();
    	...
    }

传入index索引.我们可以根据索引结合列表获取到对应Model,再通过ref的ui渲染成行.

语言边界

在这里插入图片描述
这里的思路和gpui-commpent推出的shell思路是一样的.不过shell使用的JS做业务语言.我们使用了C#做业务语言.

C#侧不处理渲染和绘制.他通过描述RenderArena来表述UI.通过ABI传递给GPUI侧

当然,shell项目我们也有介绍,请大家移步:Gpui-shell介绍

渲染过程

一次「脏」渲染(dirty render)从 View.Render(ref RenderContext) 开始,把整棵语义树写入一个平坦的 arena,Rust 校验后保留解码快照。
在这里插入图片描述

RenderArena

RenderArean是个struct.你可以在gpui-dotnet里随处可见的基本上都是struct.合理使用struct可以有效减少GC停顿.乍一看性能是不是更好了,别急,我们后面回说道这个设计.arena主要有以下四个属性来描述UI

属性 内容
NodeRecrod[] 组件 ID、标志位、UTF-8 数据区间
OpRecord[] 类型化语义操作(定长 C 布局 gpui_op_record)
ChildRecord[] parent/child 记录(铺平)
UTF-8编码byte* 文本与 key 的原始字节

我们创建的组件,放置在NodeRecrod数组里.对组件的样式设置.放置在OpRecord数组.OpRecord数组.也放了我们的事件回调.

OpRecord的Code类型我们粗略看下:

internal enum OpCode : ushort
{
    Flex = 1,
    VStack = 2,
    ItemsCenter = 3,
    JustifyCenter = 4,
    JustifyBetween = 5,
    FlexGrow = 6,
    GapPx = 100,
    PaddingPx = 101,
    WidthPx = 102,
    WidthPercent = 103,
    ...
     OnClick = 200,
    ... 
    ScrollAxis = 301,
 	SmoothScroll = 302,
 }

基本上看这个Enum,我们就知道他支持了多少gpui的功能.

我们看下我们一次渲染的调用堆栈.

在这里插入图片描述
多么简洁高效的调用.红框部分为Rust部分实现.

我们不再使用INPC的双向Binding.带来的时自己来驱动数据变化.手动触发渲染.不多不少.一点不浪费.

正文部分今天我们先到这里,明天我们会继续更新.接下来聊聊这个项目.

从昨天作者发布preview.1到今天.我们昨天测试Sample,今天已经开始解析项目实现.而这一切都要感谢AI.没有强大的AI.作者不可能3天就实现了从dotnet到gpui的调用.AI时代确实来了.我们以前按月按年计划的功能.可能在合理的AI协助下.快速高效的实现了.

但在AI时代.我们还是需要一批人,帮我们把最新的资讯.最新的技术通过肉身带到我们大家身边.搬砖工一直以来,愿意做这样的人.

希望大家多多关注点赞.再次谢谢大家

截至目前我观察,没有实现的功能大体有:

  • flex_grow_0/1, flex_shrik_0/.1, p_0/1, m_0/1
  • hotkey
  • command
    缺失部分已经咨询过作者.作者表示都在推进中.
    不光有这些,后续应该还有gui-commpent组件的实现.关注搬砖工,我带给大家带一手资讯

下篇我们会接着深入到View的生命周期,各个线程如何调用展开.我把昨天编译的sample上传到csdn上了.可以按需下载

posted on 2026-09-03 10:40  HelyCheng  阅读(19)  评论(0)    收藏  举报

导航