高阶实战 20 · 模块封装全景:从一条命令到分发 .lbmod
《LingBuilder 高阶实战系列》第 20 集,模块封装专题开篇。这一集把「模块封装」从头到尾走一遍:在欢迎页新建模块 → 认识骨架三件套 → 把模板命令改成自己的真命令 → 模块页启用 → 建一个窗口项目调用它 → 打包成 .lbmod 发给别人。学完这一集,后面的 21~25 集(命令面进阶、功能库、C++ 运行时、文档例程、生态分发)都是在这一集的骨架上加细节。全程约 40 分钟。
前置要求:会用 LingBuilder 建窗口项目(学过零基础入门即可)。想再看一遍更基础的版本,可配合《模块开发新手图文教程》。
这一集你将学会
- 模块和功能代码的区别:功能库给自己项目用,模块做出来给大家用
- 欢迎页「新建模块」两种模式:从模板新建 / 打开 .lbmod 模块包
- 骨架三件套:清单
lingbuilder.module.json、C++ 桥接头、C++ 实现 - 改命令 = 同时改「给人看的 contributes」和「给编译器看的 bindings」
- 清单校验诊断怎么看(本集真踩了一个:binding 参数写错字段名)
- 打包
.lbmod模块包,与别人拿到包后的两种装法
1. 三十秒理解:模块 vs 功能代码
功能代码(功能库) 模块(.lbmod)
只属于一个项目 装到任何工作区的任何项目
复制到别的项目要带源码 双击/导入即可安装
只能自己用 可以发给别人模块内部是真正的 C++ 代码,F5 构建时直接编译进最终程序——没有性能损失。本集我们做一个最小但完整的「文本工具模块」:两条统计命令 + 一个版本常量。
2. 欢迎页新建模块
打开 LingBuilder,在欢迎页点**「新建模块」,弹出模块窗口后保持「从模板新建」**页签:

填四项信息:
- 模块 ID:模块的英文「身份证号」,小写字母/数字开头,可含点、下划线、中划线。我们填
lingbuilder.demo.texttools(建议都用lingbuilder.demo.开头避免撞名); - 模块名称:中文显示名,填「文本工具模块」;
- 分类:八选一(界面/系统/网络/数据库/图像/AI/构建/其他),保持「系统」;
- 模块说明:一句话说明模块是干什么的,会显示在模块详情页。

点**「创建模块」**,出现绿色提示「模块源码已就绪」就成功了。注意提示里的三条后续路径:① 工作台模块页启用;② 「文件 → 打开文件」编辑清单与 C++ 源码;③ 模块页「模块包制作」发布 .lbmod:

3. 骨架三件套:去哪里改
创建好的骨架落在工作区 .lingbuilder/module-build/lingbuilder.demo.texttools/:
lingbuilder.module.json ← 模块清单:命令、常量、文档、编译配置都登记在这里
include/module_bridge.h ← C++ 桥接头(函数声明)
src/module_bridge.cpp ← C++ 实现(命令的真身)
docs/usage.md ← 随包使用说明
examples/最小示例.lcpp ← 例程源码(模块详情页「示例」分组展示)模板骨架自带一条占位的「示例命令」和一个「示例常量」,编译目标只有 32 位(win32)。用「文件 → 打开文件」或任何外部编辑器(记事本/VS Code 都行)直接改这些普通文本文件即可——IDE 直接消费磁盘上的最新内容,改完不用重装,下一次补全、诊断、F5 就是新的。
4. 改命令:把示例命令换成真命令
我们要两条命令:
文本工具_统计字符(文本)→ 整数型:字符数(1 个汉字算 1 个)文本工具_统计汉字数(文本)→ 整数型:只数汉字
4.1 改 C++ 桥接头 include/module_bridge.h
#pragma once
#include <string>
// 模块桥接函数声明:清单 bindings 里的 runtimeName 叫什么,这里就声明什么。
int TextTools_CountChars(const wchar_t* text);
int TextTools_CountHan(const wchar_t* text);参数写
const wchar_t*(文本型参数的固定写法),返回int(整数型返回值的固定写法)。
4.2 改 C++ 实现 src/module_bridge.cpp
#include "module_bridge.h"
#include <cwchar>
// 统计字符:按 UTF-16 码元计数(1 个汉字算 1 个)。
int TextTools_CountChars(const wchar_t* text) {
return text ? (int)wcslen(text) : 0;
}
// 统计汉字数:只统计 CJK 基本区(U+4E00 ~ U+9FFF)的汉字。
int TextTools_CountHan(const wchar_t* text) {
if (text == nullptr) return 0;
int count = 0;
for (const wchar_t* p = text; *p != L'\0'; ++p) {
if (*p >= 0x4E00 && *p <= 0x9FFF) ++count;
}
return count;
}4.3 改清单 lingbuilder.module.json
清单里和命令相关的有两块,命令名必须一致:
contributes.commands:给人看的(命令名、签名、说明、补全片段),类型用中文(整数型);bindings.commands:给编译器看的(C++ 函数名runtimeName、参数 ABI 类型),类型用英文(wideString= 文本型、int= 整数型)。
再把 targets 补一个 x64 目标(模板默认只有 win32;F5 常用 64 位构建,少了 x64 目标构建会报 C1083 找不到符号——这是新手最容易踩的坑)。完整清单见源码包,关键字段长这样:
"bindings": {
"commands": [
{ "command": "文本工具_统计字符", "runtimeName": "TextTools_CountChars",
"parameters": [ { "name": "文本", "type": "wideString", "description": "要统计的原文文本。" } ],
"returnType": "int", "example": "文本工具_统计字符(\"你好 LingBuilder\")" }
]
}⚠️ 本集真踩的坑:binding 参数的字段名是
type,不是cppType。写错后模块在模块页里「消失」——其实它在,只是清单校验未通过被标成了无效模块。遇到「搜不到自己的模块」,先在模块详情/扫描诊断里看中文校验信息(形如bindings.commands[0].parameters[0].type 不受支持),按提示改字段名即可。
4.4 顺手把 docs 和示例补上
docs/usage.md 写两条命令的说明表格;examples/最小示例.lcpp 用控制台形态(后面 24 集会真正打开它):
类 程序
公开 整数型 启动()
' 文本工具模块 最小示例:统计字符与汉字数
调试输出(文本工具_统计字符("你好 LingBuilder"))
调试输出(文本工具_统计汉字数("你好,世界!Hello"))
调试输出(#文本工具_版本)
返回(0)
结束
结束类5. 模块页:找到并启用
回到工作台,点活动栏**「模块」,搜索「文本工具」——模块卡片带金色「开发源」**标记,表示它直接消费你的源码目录(不是安装副本):

点卡片打开模块详情:标识符、版本、分类、**构建目标·2(Win32 + x64)**都在这里,「接口」页能看到两条命令的完整签名:

注意:模块是按项目启用的。先确认当前项目是你要用它的那个项目(下一节建好项目后再点启用也一样)。
6. 建调用方项目,写调用代码
菜单「文件(F) → 新建项目」,类型选 Windows 界面设计:

项目名称填「文本工具演示」,点「创建项目」:

回到模块页点开文本工具模块详情,点**「启用」**——按钮变成红色「禁用」、侧栏出现「已启用 1」、输出面板记录「【模块】启用 文本工具模块。」:

画 6 个控件:说明标签、输入框(默认内容 你好 LingBuilder,中文模块真方便!)、两个按钮、结果列表框、状态标签:

双击 MainWindow.lcpp,在三个事件块里写调用代码:

类 MainWindow
事件 _MainWindow_创建完毕()
控件_添加项目(结果列表, "就绪:模块已启用,点下方两个按钮试试。")
结束「① 统计字符与汉字数」按钮:取输入框原文,分别调用两条命令,把结果写进列表:

事件 _统计按钮_被单击()
局部 文本型 内容
内容 = 控件_取文本(内容输入框)
控件_清空项目(结果列表)
控件_添加项目(结果列表, "原文:" + 内容)
控件_添加项目(结果列表, "文本工具_统计字符 → " + 到文本(文本工具_统计字符(内容)) + " 个字符")
控件_添加项目(结果列表, "文本工具_统计汉字数 → " + 到文本(文本工具_统计汉字数(内容)) + " 个汉字")
列表框_滚动到项(结果列表, 控件_取项目数量(结果列表) - 1)
控件_设置文本(状态标签, "统计完成。")
结束「② 读常量」按钮:模块清单里的常量在源码中用 #常量名 直接引用:

事件 _常量按钮_被单击()
控件_添加项目(结果列表, "#文本工具_版本 = " + 到文本(#文本工具_版本) + "(模块清单里的常量)")
列表框_滚动到项(结果列表, 控件_取项目数量(结果列表) - 1)
控件_设置文本(状态标签, "常量读取完成。")
结束
结束类输入
文本工具时补全会直接列出模块命令和完整签名——模块一旦启用,命令和内置命令的输入体验完全一致。
7. 编译、运行、真机验证
编译后先看底部错误列表(0)——零报错再运行:


点「① 统计字符与汉字数」:你好 LingBuilder,中文模块真方便! = 23 个字符(汉字+字母+标点都算 1 个)、9 个汉字(你好中文模块真方便)——两个数字都对得上:

点「② 读常量」:#文本工具_版本 = 100(清单里的 1.00 版本常量):

到这里,你写的 C++ 已经以模块命令的形式真实跑在 exe 里了。
8. 打包 .lbmod,发给别人
模块页右上**「…」→「模块包制作」**,填两项:
- 模块目录:
.lingbuilder/module-build/lingbuilder.demo.texttools - 导出路径:
.lingbuilder/module-packages/lingbuilder.demo.texttools-1.0.0.lbmod

点**「导出 .lbmod」**,输出面板提示「【模块包】已导出 ……」即成功,.lbmod 就落在工作区的 module-packages 目录:

9. 别人怎么装你的包
拿到 .lbmod 的人有两条装法(模块页「…」菜单里都有关口):

- 欢迎页 → 新建模块 → 「打开 .lbmod 模块包」页签:填 .lbmod 文件完整路径,登记为开发源(能看能改能启用);
- 模块页 → 「…」→「安装 .lbmod」:按安装包流程装入
.lingbuilder/modules。
装好后在模块详情「接口」页能看到和你机器上一模一样的命令清单。25 集会把安装/卸载/升级/市场这些生态能力展开讲。
下一集预告
21 集讲命令面进阶:带默认值参数、控件参数 controlRef、常量与代码片段 snippets、中文别名的完整写法。
源码包
本集完整项目(含调用方源码)已打包:文本工具演示.lcpppkg——在 LingBuilder 里「文件 → 打开 LCPP 源码包」即可一键导入运行。