<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>记忆碎片</title><description/><link>https://memo.yuchanns.xyz</link><item><title>大部分国内的模型, 在结构化输出和工具调用方面都做得不如 OpenAI 和 Anthropic, 两者无法兼顾</title><link>https://memo.yuchanns.xyz/posts/63</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/63</guid><pubDate>Thu, 08 Jan 2026 08:40:06 GMT</pubDate><content:encoded>大部分国内的模型, 在结构化输出和工具调用方面都做得不如 OpenAI 和 Anthropic, 两者无法兼顾。这种情况下我们应该优先选择工具调用能力强的模型, 因为在当前背景下, 没有工具调用能力的模型没有太大用处。况且, 我们也可以伪造一个输出工具, 让模型把你需要的结构化输出结果通过工具调用的形式填入, 变相解决了结构化输出的问题</content:encoded></item><item><title>今年有挺多事情想做的，想做游戏，想学习 blender 想学习 aseprite</title><link>https://memo.yuchanns.xyz/posts/62</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/62</guid><pubDate>Tue, 06 Jan 2026 14:23:56 GMT</pubDate><content:encoded>今年有挺多事情想做的，想做游戏，想学习 blender 想学习 aseprite</content:encoded></item><item><title>所以我应该不止是让 AI 替我做，而是通过它学习，辅助我掌握</title><link>https://memo.yuchanns.xyz/posts/61</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/61</guid><pubDate>Tue, 06 Jan 2026 12:59:51 GMT</pubDate><content:encoded>所以我应该不止是让 AI 替我做，而是通过它学习，辅助我掌握。我知道现在很多人提倡的是习惯 AI 自动化，但我觉得即使我克服这种不适，也会变废</content:encoded></item><item><title>今天终于确认了我对 AI 的使用态度</title><link>https://memo.yuchanns.xyz/posts/60</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/60</guid><pubDate>Tue, 06 Jan 2026 12:57:47 GMT</pubDate><content:encoded>今天终于确认了我对 AI 的使用态度。我还是应该克制。设想 AI 在最聪明的状态，它可以取代我，无所不能，那么我更应该做的是学习，掌握它能给予我的知识。我所恐惧的其实是把一切交给 AI 然后失控的感觉。自动化最重要的就是人类可以介入。 AI 可以帮我干活，但我应该理解它在干什么，至少我要懂一些基础，才能控制方向，成为它的 leader.</content:encoded></item><item><title>从这份 lsblk 输出可以确认：- nvme0n1p1 1G → **EFI 系统分区**（`/boot/efi`）  - nvme0n1p2 2G → /boot 分区  - nvme0n1p3 1.8T → 物理卷，其下逻辑卷 ubuntu--vg-ubuntu--lv 才是 真正的根（/）  下面给出**完全离线**的挂载 + GRUB 重装命令，直接复制即可</title><link>https://memo.yuchanns.xyz/posts/59</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/59</guid><pubDate>Sat, 22 Nov 2025 06:00:48 GMT</pubDate><content:encoded>从这份&lt;code&gt; lsblk &lt;/code&gt;输出可以确认：&lt;br /&gt;&lt;br /&gt;-&lt;b&gt; nvme0n1p1 &lt;/b&gt;1G → **EFI 系统分区**（`/boot/efi`）  &lt;br /&gt;-&lt;b&gt; nvme0n1p2 &lt;/b&gt;2G →&lt;b&gt; /boot 分区 &lt;/b&gt; &lt;br /&gt;-&lt;b&gt; nvme0n1p3 &lt;/b&gt;1.8T → 物理卷，其下逻辑卷&lt;code&gt; ubuntu--vg-ubuntu--lv &lt;/code&gt;才是&lt;b&gt; 真正的根（/） &lt;/b&gt; &lt;br /&gt;&lt;br /&gt;下面给出**完全离线**的挂载 + GRUB 重装命令，直接复制即可。&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;### 1. 启动 LiveCD → 打开终端  &lt;br /&gt;“Try Ubuntu” 进入桌面后 `Ctrl+Alt+T`。&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;### 2. 激活 LVM 并挂载各分区  &lt;pre&gt;&lt;code&gt;sudo vgchange &lt;span&gt;-&lt;/span&gt;ay          &lt;span&gt;#&lt;/span&gt; 激活卷组（否则逻辑卷不可见）
sudo mkdir &lt;span&gt;-&lt;/span&gt;p &lt;span&gt;/&lt;/span&gt;mnt&lt;span&gt;/&lt;/span&gt;ubuntu
sudo mount &lt;span&gt;/&lt;/span&gt;dev&lt;span&gt;/&lt;/span&gt;mapper&lt;span&gt;/&lt;/span&gt;ubuntu&lt;span&gt;--vg-ubuntu--lv /mnt/ubuntu   # 挂载根（LVM）&lt;/span&gt;
sudo mount &lt;span&gt;/&lt;/span&gt;dev&lt;span&gt;/&lt;/span&gt;nvme0n1p2 &lt;span&gt;/&lt;/span&gt;mnt&lt;span&gt;/&lt;/span&gt;ubuntu&lt;span&gt;/&lt;/span&gt;boot                 &lt;span&gt;#&lt;/span&gt; 挂载 &lt;span&gt;/&lt;/span&gt;boot
sudo mount &lt;span&gt;/&lt;/span&gt;dev&lt;span&gt;/&lt;/span&gt;nvme0n1p1 &lt;span&gt;/&lt;/span&gt;mnt&lt;span&gt;/&lt;/span&gt;ubuntu&lt;span&gt;/&lt;/span&gt;boot&lt;span&gt;/&lt;/span&gt;efi              &lt;span&gt;#&lt;/span&gt; 挂载 EFI
&lt;span&gt;#&lt;/span&gt; 绑定虚拟文件系统
&lt;span&gt;for&lt;/span&gt; i &lt;span&gt;in&lt;/span&gt; dev proc sys&lt;span&gt;;&lt;/span&gt; &lt;span&gt;do&lt;/span&gt; sudo mount &lt;span&gt;--bind /$i /mnt/ubuntu/$i; done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;### 3. 进入原系统环境  &lt;pre&gt;&lt;code&gt;sudo chroot /mnt/ubuntu /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;### 4. 重装 GRUB（UEFI 模式，离线）  &lt;pre&gt;&lt;code&gt;grub&lt;span&gt;-&lt;/span&gt;install &lt;span&gt;--target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu --removable&lt;/span&gt;
update&lt;span&gt;-&lt;/span&gt;grub
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;### 5. 退出并重启  &lt;pre&gt;&lt;code&gt;exit
sudo reboot
&lt;/code&gt;&lt;/pre&gt;拔掉 LiveCD，GRUB 菜单应已恢复，可正常进入 Ubuntu。</content:encoded></item><item><title>因为 soluna 支持写 app 应用，而我最近正好打算为我父母和妻子编写一个抖音直播录制工具 app，想要试试</title><link>https://memo.yuchanns.xyz/posts/58</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/58</guid><pubDate>Tue, 14 Oct 2025 01:59:58 GMT</pubDate><content:encoded>因为 soluna 支持写 app 应用，而我最近正好打算为我父母和妻子编写一个抖音直播录制工具 app，想要试试。不过这有个问题，就是录制部分需要使用 ffmpeg 来进行，而 ltask 虽然可以 N:M 调度 lua 虚拟机，但是如果像 ffmpeg  这种阻塞调用，就会导致线程阻塞了。&lt;br /&gt;当然，解决方法也是有的，比如引入事件循环，将 fork 的进程挂载到事件循环上，比如使用 bee.lua 就是个不错的选择。不过这意味着需要修改 soluna 的源码，在虚拟机注入 bee.lua。但我又不太想修改源码。首先这个功能对于 soluna 本身没有什么必要，因此我倾向于不到上游提需求；其次，我也不想修改源码，方便后续同步上游最新更新。&lt;br /&gt;这时候我突然理解了 C 语言的一个优点了。&lt;br /&gt;ltask 预留了一个 -DLTASK_EXTERNAL_OPENLIBS 选项，soluna 本身的库就是通过 -DLTASK_EXTERNAL_OPENLIBS=soluna_openlibs 在编译时注入符号的。&lt;br /&gt;这意味着，我只需要把 soluna 设置为我的子仓库依赖，然后创建一个例如 soluna_app.c 的文件。在这个文件里面我创建一个 soluna_app_openlibs 函数，它内部除了调用 soluna_openlibs 还注入 bee.lua。最后在编译时，我把定义改成 -DLTASK_EXTERNAL_OPENLIBS=soluna_app_openlibs 从而就可以实现不更改源码，增量编译增加功能</content:encoded></item><item><title>yoga 在排版中的具体作用是什么呢？举个简单的例子，就拿 soluna/test/layout.lua 来举例:我们创建如下一个 hud 排版, 它是一个简单的左右结构</title><link>https://memo.yuchanns.xyz/posts/57</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/57</guid><pubDate>Sun, 12 Oct 2025 15:19:19 GMT</pubDate><content:encoded>yoga 在排版中的具体作用是什么呢？举个简单的例子，就拿 &lt;code&gt;soluna/test/layout.lua&lt;/code&gt; 来举例:&lt;br /&gt;我们创建如下一个 hud 排版, 它是一个简单的左右结构。其中左边我们定义了宽度为 400, 右边则是填满剩下的宽度。两者都填充满高度。另外右边是上下结构，其中第一个 node 占了70%的宽度，第二个占了30%的宽度。&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
local hud = &lt;span&gt;[&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;
&lt;span&gt;id&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; screen
&lt;span&gt;padding&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;10&lt;/span&gt;
&lt;span&gt;direction&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; row
&lt;span&gt;gap&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;10&lt;/span&gt;
&lt;span&gt;left&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;
 &lt;span&gt;width&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;400&lt;/span&gt;
 &lt;span&gt;background&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;0x40000000&lt;/span&gt;
&lt;span&gt;right&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;
 &lt;span&gt;flex&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;
 &lt;span&gt;gap&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;10&lt;/span&gt;
 &lt;span&gt;node&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;
  &lt;span&gt;flex&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.7&lt;/span&gt;
  &lt;span&gt;background&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;0x40ffffff&lt;/span&gt;
 &lt;span&gt;node&lt;/span&gt; &lt;span&gt;:&lt;/span&gt;
  &lt;span&gt;flex&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.3&lt;/span&gt;
  &lt;span&gt;background&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;0x40ffffff&lt;/span&gt;
&lt;span&gt;]&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;此时单单使用这个 hud 我们还做不了什么。&lt;br /&gt;紧接着我们在脚本入参中，可以获得启动时窗口的宽高, 我们可以将其设置到 screen 上:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
&lt;span&gt;local&lt;/span&gt; dom &lt;span&gt;=&lt;/span&gt; layout&lt;span&gt;.&lt;/span&gt;&lt;span&gt;load&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;datalist&lt;span&gt;.&lt;/span&gt;&lt;span&gt;parse_list&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;hud&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;local&lt;/span&gt; screen &lt;span&gt;=&lt;/span&gt; dom&lt;span&gt;.&lt;/span&gt;screen

&lt;span&gt;local&lt;/span&gt; &lt;span&gt;function&lt;/span&gt; &lt;span&gt;calc_hub&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
 screen&lt;span&gt;.&lt;/span&gt;width &lt;span&gt;=&lt;/span&gt; args&lt;span&gt;.&lt;/span&gt;width
 screen&lt;span&gt;.&lt;/span&gt;height &lt;span&gt;=&lt;/span&gt; args&lt;span&gt;.&lt;/span&gt;height
 &lt;span&gt;return&lt;/span&gt; layout&lt;span&gt;.&lt;/span&gt;&lt;span&gt;calc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;dom&lt;span&gt;)&lt;/span&gt;
&lt;span&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;上面这段代码做了三件事: 加载布局到 yoga 中, 然后为 screen 设置宽高, 接着调用 calc 计算布局。&lt;br /&gt;最后，假设宽是800,高是600,那么 yoga 会根据 left 的宽，计算出 right 的宽度为 400, 两者的高度都是 600; 而在 right 中第一个 node 的高 420, 第二个则是 180.&lt;br /&gt;最后我们将计算结果使用 matquad 材质构建出实体:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
&lt;span&gt;local&lt;/span&gt; &lt;span&gt;function&lt;/span&gt; &lt;span&gt;draw_hud&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
 &lt;span&gt;for&lt;/span&gt; _&lt;span&gt;,&lt;/span&gt; obj &lt;span&gt;in&lt;/span&gt; &lt;span&gt;ipairs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;draw_list&lt;span&gt;)&lt;/span&gt; &lt;span&gt;do&lt;/span&gt;
  args&lt;span&gt;.&lt;/span&gt;batch&lt;span&gt;:&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;matquad&lt;span&gt;.&lt;/span&gt;&lt;span&gt;quad&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;obj&lt;span&gt;.&lt;/span&gt;w&lt;span&gt;,&lt;/span&gt; obj&lt;span&gt;.&lt;/span&gt;h&lt;span&gt;,&lt;/span&gt; obj&lt;span&gt;.&lt;/span&gt;background&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; obj&lt;span&gt;.&lt;/span&gt;x&lt;span&gt;,&lt;/span&gt; obj&lt;span&gt;.&lt;/span&gt;y&lt;span&gt;)&lt;/span&gt;
 &lt;span&gt;end&lt;/span&gt;
&lt;span&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;并使用 &lt;code&gt;batch:add&lt;/code&gt; 提交绘制命令，告诉框架，我要创建一个四边形(quad), 它宽w高h, 使用背景色 background, 绘制时的坐标是 x 和 y。&lt;br /&gt;最后在 frame 中调用该函数，也就是每一帧都绘制。&lt;br /&gt;当窗口发生变化时，我们又更新宽高，然后重新计算 node 布局信息，这样就可以在下一帧及时更新整体布局。</content:encoded></item><item><title>batch 是 soluna 在调用我们编写的 main.lua 时传入的参数</title><link>https://memo.yuchanns.xyz/posts/56</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/56</guid><pubDate>Sun, 12 Oct 2025 14:51:18 GMT</pubDate><content:encoded>batch 是 soluna 在调用我们编写的 main.lua 时传入的参数。我们绘制时只需调用 batch:add, 这意味着，我们可以在任意地方调用，并不是说一定要在同一个地方调用。这有助于低耦合，高内聚。当我们需要绘制多个模块的 ui 时，每个 ui 可以独立传入 batch, 在内部实现排版和绘制。一般来说最佳实践是每个模块都具有一个 draw 函数和 update 函数。这样遍历多个模块时，聚合的函数只需要先 update 再 draw, 而不需要关注具体内部实现，各个模块也是独立实现的。 deepfuture 就是如此做。</content:encoded></item><item><title>在绘制 ui 时，我们可以有很多个 node，而不仅仅是一个 node</title><link>https://memo.yuchanns.xyz/posts/55</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/55</guid><pubDate>Sun, 12 Oct 2025 14:38:48 GMT</pubDate><content:encoded>在绘制 ui 时，我们可以有很多个 node，而不仅仅是一个 node。例如，bg 是一个 node， hud 也是一个 node。每个 node 都需要通过调用 calc 方法来更新结构。因此当整个界面的不同部位更新频率不同时，我们可以将其分开成多个 node，单独 calc 其变更，避免每帧都需要对整个 ui 重新计算，减轻压力。另外一个 node 中的 id 都是唯一的，而在多个 node 中 id 是可以重复的。这个 id 只是 yoga 用来计算使用，或者我们可以通过 id 来获取和设置 yoga 中的布局信息。这是我一开始误解的一点。我使用 soluna 编写一个 todo app 时，将整个页面都描绘成一个固定的 node ，结果在更新、计算时，遇到了动态添加的困难。&lt;br /&gt;当我静下心来仔细阅读 deepfuture 代码时，发现了这一点。</content:encoded></item><item><title>soluna 使用 facebook/yoga 作为排版工具</title><link>https://memo.yuchanns.xyz/posts/54</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/54</guid><pubDate>Sun, 12 Oct 2025 14:33:16 GMT</pubDate><content:encoded>soluna 使用 facebook/yoga 作为排版工具。这个工具是 react native 的基础设施，仅仅是负责排版，不负责渲染。在 soluna 中，我们可以用 datalist 描述排版，然后将其载入到 yoga 中，生成一个 node, 接着根据 node 结构来生成渲染指令。这里的渲染指令是指传入 batch:add 的参数。因为实际渲染都是通过 batch 来实现的。关于 batch:add 函数的 api 的函数签名描述如下:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;
&lt;span&gt;-&lt;/span&gt; batch&lt;span&gt;:&lt;/span&gt;add(obj &lt;span&gt;[&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; x &lt;span&gt;[&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; y&lt;span&gt;]&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;)
&lt;span&gt;-&lt;/span&gt; &lt;span&gt;obj 可以是&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; 正整数 sprite id；材质模块返回的 userdata（例如 matquad.quad、mattext.block(…) 的结果）；或已经打包好的二进制流。附带坐标则先平移后提交。
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;可以说是很简单了，把材质和坐标放进去就可以绘制。&lt;br /&gt;但是正因为如此简单，如果我们要直接使用它来绘制整个画面，将会较为复杂。这就是为什么我们需要一个排版工具。这个排版工具实际上就是通过一系列抽象，使得我们在设计某些具体细节时，不需要关注全局。最后通过一次 calc 计算，替我们计算某个节点的全局坐标，这样我们就可以较为轻松的绘制。当然，如果有别的排版工具，也完全可以不使用 yoga 进行排版，这不是一个必要条件。</content:encoded></item><item><title>最近开始尝试学习如何使用 soluna，但是我太过急躁了，只是弄清了一点 BATCH (批渲染) API 的用法，就急不可耐地试图编写一个 TODO APP, 而且还是让 AI 写的</title><link>https://memo.yuchanns.xyz/posts/53</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/53</guid><pubDate>Sun, 12 Oct 2025 14:19:07 GMT</pubDate><content:encoded>最近开始尝试学习如何使用 soluna，但是我太过急躁了，只是弄清了一点 BATCH (批渲染) API 的用法，就急不可耐地试图编写一个 TODO APP, 而且还是让 AI 写的。其结果就是代码质量失控，我完全不知道 AI 写了什么，任凭其忽悠。于是我变得急躁，失去耐心，失去谦虚。最后搞砸了一切，从头再来</content:encoded></item><item><title>最近给 soluna 提交了一些 pr 接下来还可以添加一个 icon 特性，然后 deepfuture 可以添加设置界面</title><link>https://memo.yuchanns.xyz/posts/52</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/52</guid><pubDate>Wed, 08 Oct 2025 16:24:43 GMT</pubDate><content:encoded>最近给 soluna 提交了一些 pr &lt;br /&gt;接下来还可以添加一个 icon 特性，然后 deepfuture 可以添加设置界面</content:encoded></item><item><title>内置还要有一个 config 服务，这样插件可以使用该服务创建和读取配置</title><link>https://memo.yuchanns.xyz/posts/51</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/51</guid><pubDate>Thu, 02 Oct 2025 20:01:46 GMT</pubDate><content:encoded>内置还要有一个 config 服务，这样插件可以使用该服务创建和读取配置。例如刮削，需要读取 tmdb api key ，没有时，需要页面展示配置指引</content:encoded></item><item><title>同理， 刮削服务 scrap.lua 也可以被 download 通知启动刮削</title><link>https://memo.yuchanns.xyz/posts/50</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/50</guid><pubDate>Thu, 02 Oct 2025 19:49:07 GMT</pubDate><content:encoded>同理， 刮削服务 scrap.lua 也可以被 download 通知启动刮削</content:encoded></item><item><title>然后再创建一个 download 服务，调用 rss.lua 提供的 notify 接口注册通知</title><link>https://memo.yuchanns.xyz/posts/49</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/49</guid><pubDate>Thu, 02 Oct 2025 19:47:29 GMT</pubDate><content:encoded>然后再创建一个 download 服务，调用 rss.lua 提供的 notify 接口注册通知。 rss 有更新时就会通知到 download 服务进行下载。</content:encoded></item><item><title>service 内置一个 plugin.lua ，专门启动插件 service</title><link>https://memo.yuchanns.xyz/posts/48</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/48</guid><pubDate>Thu, 02 Oct 2025 19:45:19 GMT</pubDate><content:encoded>service 内置一个 plugin.lua ，专门启动插件 service。例如，我们有一个 service 叫作 rss.lua ，在插件页面点击下载后，会携带插件代码，ltask.call plugin service 请求创建 rss service，定期检查 rss ，并注册一个路由用来展示 rss 功能页面。</content:encoded></item><item><title>感觉 ltask 天然适合 dalbox</title><link>https://memo.yuchanns.xyz/posts/47</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/47</guid><pubDate>Thu, 02 Oct 2025 19:13:47 GMT</pubDate><content:encoded>感觉 ltask 天然适合 dalbox。每个插件就是一个 service。前面说的订阅，下载，AI 字幕都可以是单独的线程。 http 也是多个  service 负载均衡，数据库也是一个单独 service ，模板渲染也是单独 service</content:encoded></item><item><title>想做的几件事- dalbox- gomalloc- shader</title><link>https://memo.yuchanns.xyz/posts/46</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/46</guid><pubDate>Sat, 27 Sep 2025 15:33:45 GMT</pubDate><content:encoded>想做的几件事&lt;br /&gt;- dalbox&lt;br /&gt;- gomalloc&lt;br /&gt;- shader</content:encoded></item><item><title>我大概明白了，是检查 LTASK_EXTERNAL_OPENLIBS 是否定义了</title><link>https://memo.yuchanns.xyz/posts/45</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/45</guid><pubDate>Sun, 17 Aug 2025 18:05:06 GMT</pubDate><content:encoded>我大概明白了，是检查 LTASK_EXTERNAL_OPENLIBS 是否定义了。如果没有，就默认打开标准库。所以可以通过这个方式注入。不过 ant 的实现方式更彻底。直接替换掉 luaL_openlibs 。看来我的 lua binding 实现需要做一些调整，以便于支持这种操作</content:encoded></item><item><title>在为 ltask-go 编写 examples 时我陷入了困境，无法同时成功跑通三个平台的 bee.lua </title><link>https://memo.yuchanns.xyz/posts/44</link><guid isPermaLink="true">https://memo.yuchanns.xyz/posts/44</guid><pubDate>Sun, 17 Aug 2025 18:00:02 GMT</pubDate><content:encoded>在为 ltask-go 编写 examples 时我陷入了困境，无法同时成功跑通三个平台的 bee.lua 。主要是无法跑通 windows 平台的。经过研究 ejoy/ant 的代码，我终于弄清楚了。嘿嘿，果然看不懂只是暂时的，迟早会弄懂。&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://github.com/ejoy/ant/blob/master/runtime/common/modules.c&quot; target=&quot;_blank&quot;&gt;https://github.com/ejoy/ant/blob/master/runtime/common/modules.c&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ant 采用的方式是把所有的 clibs 的 luaopen 函数统一注入到自己的入口，这样 lua 代码就可以直接使用，而不需要寻找同名的 dylib&lt;br /&gt;&lt;br /&gt;目前我还有一个疑惑，ltask 创建多个服务时，只会打开标准库。不知道是怎么注入的？难道是宏可以重写？&lt;a href=&quot;https://github.com/ejoy/ant/blob/master/runtime/common/modules.c&quot; target=&quot;_blank&quot;&gt;
  
  &lt;div&gt;GitHub&lt;/div&gt;
  &lt;img class=&quot;link_preview_image&quot; alt=&quot;ant/runtime/common/modules.c at master · ejoy/ant&quot; src=&quot;/static/https://cdn4.telesco.pe/file/ZC1UdOTFLlulnQRrdoEXobc8pZ08FXjrWD11WEAkAO1fqxYSEapbNOwOfoFu8bAZ322Ot4aJUtYJlZEIIWnv3xWTbpoProDZXofLiweGMNBzhC_mpCrYKM9Q0d1QK8PAZczd2euge4SMKtx_2sKNBnSQ_BdNks8UlE68U1HyGwX1sq4vTJB_yHPaTwgEi8BCIk7IZlVOktV86nRxlMbEwrVBzoW5OlOyvdwx96VdzmFoiyA0BUtO-bGwsJaFNkC4lSi0ZbemUkIEDOuJWFjWrxSId-dgndDKbng1UHItnQqhkxxiD1B9-rlitAY4XtkS6AwRvW40iG4bDIzAxcSh-Q.jpg&quot; loading=&quot;lazy&quot; /&gt;
  &lt;div&gt;ant/runtime/common/modules.c at master · ejoy/ant&lt;/div&gt;
  &lt;div&gt;Ant game engine. Contribute to ejoy/ant development by creating an account on GitHub.&lt;/div&gt;
&lt;/a&gt;</content:encoded></item></channel></rss>