Rust开发VFP FLL实践:编写木瓜myfll的CursorToStr和StrToCursor兼容函数,附源码及编译方法
`cursorrust.fll` 是用 Rust 开发的 **32 位 Visual FoxPro 9 FLL**,实现木瓜 MyFll 的游标转字符串、字符串还原游标这组兼容函数,并对游标处理做了性能优化。本项目提供 `CursorToStrRust` 和 `StrToCursorRust` 两个 VFP 函数。## 使用
```foxpro
SET LIBRARY TO cursorrust.fll ADDITIVE
CREATE CURSOR orders (order_id I, customer C(20))
INSERT INTO orders VALUES (1, "Alice")
lcWire = CursorToStrRust("orders", .T.)
llOK = StrToCursorRust(m.lcWire, "orders:received_orders")
IF m.llOK
SELECT received_orders
BROWSE
ENDIF
```
`CursorToStrRust(cCursorList[, lCompress])` 把已打开的游标编码为二进制字符串。`cCursorList` 可写一个游标名,也可用逗号分隔多个游标;`.T.` 启用 zlib 压缩,省略或 `.F.` 不压缩。
`StrToCursorRust(cWire[, cSelector])` 从该字符串建立游标,成功返回 `.T.`。`"orders:received_orders"` 表示读取字符串中名为 `orders` 的游标,并在当前 VFP 中建立 `received_orders`。字符串可能含 `CHR(0)`,保存或传输时必须原样保留全部字节。多游标、改名及错误处理见 [使用说明](使用说明.txt)。
## 本项目怎样提速
**序列化的普通路径**逐条遍历 VFP 游标,并通过扩展 API 读取字段。记录数越多,跨 VFP/Rust 边界的调用次数越多。`src/cursor_bridge.rs` 为符合条件的物理 DBF 增加了快速路径:用 VFP 的 `FILETOSTR(DBF(...))` 一次取得文件内容,解析 DBF 表头和记录区,直接构造相同的游标线格式。这减少了逐条定位和逐字段读取的调用。
快速路径先确认工作区只读,或处于**无缓冲、无事务**状态;字段必须完整且按原顺序排列,全部为非空的 `C`/`I`;没有 `FILTER()` 和 `ORDER()`。还要核对 DBF 文件路径、表头、字段描述、记录宽度、文件长度与 VFP 的记录数,并逐条检查删除标记。任何条件不符就回退到普通路径,继续按 VFP 当前工作区的过滤、排序、缓冲数据和字段选择读取。500 万条测试表符合这条路径的输入条件。
**还原的普通路径**每条记录调用 `_DBAppend`,每个字段再调用 `_DBReplace`,大量记录会产生大量 VFP 扩展 API 调用。VFP 9 SDK 的 `pro_ext.h` 实际声明了 `int FASTCALL _DBAppendRecords(int workarea, unsigned short nrecs, char FAR *buffer)`,但微软帮助文档没有介绍它的用法;这个批量追加接口的实际使用方法是本项目作者自行试验确认的,也是还原提速的关键。
本项目先把线格式记录转换成 VFP 的原生记录缓冲区,再把工作区号、批次记录数和缓冲区指针交给 `_DBAppendRecords`,由 VFP 引擎一次追加一批。每批最多 32,767 条,整块缓冲区最多 64 MiB。批量路径要求字段无 NULL,类型限于 `C`、`N`、`F`、`B`、`I`、`Y`、`L`,其中 `N`/`F` 宽度不超过 64。布局或字段值无法转换、或缓冲区超限时,改走逐条还原;如果 `_DBAppendRecords` 本身返回错误,则报告还原失败。程序不绕过 VFP 引擎直接写 DBF 文件。
`src/cursor_wire.rs` 进一步减少大量小记录的分配:不超过 8 字节的字段值和不超过 4 个字段的行放在结构体内部;解码后保留线格式缓冲区,按记录和字段位置取切片,避免先把所有记录再复制成另一套完整对象。压缩采用 zlib,能减少传输字节,但会增加计算时间。
## 编译
构建需要 Rust 1.77.2、`i686-pc-windows-gnu` 目标,以及 32 位 MinGW GCC 和 objdump;**不需要微软编译器**。仓库中的 `libwinapims.a` 是构建时使用的 VFP SDK 静态导入库。`build.bat` 顶部的 `MINGW_BIN` 明确指定 MinGW 的 `bin` 目录;换一台电脑编译时,将默认路径改成那台电脑的实际安装路径,或在运行前设置 `MINGW_BIN` 环境变量。脚本会检查 GCC 是否为 `i686-w64-mingw32`,并显式指定它作为 Cargo 的链接器。
在项目目录运行:
```bat
build.bat
```
脚本构建 32 位 DLL,检查 PE 格式和 VFP 必需导出,然后在项目目录生成 `cursorrust.fll`。
`cursorrust.fll` 可随 VFP 应用绿色部署:将文件放到 VFP 能找到的位置并用 `SET LIBRARY TO ... ADDITIVE` 加载。目标系统为 **Windows 7 SP1 及以上**;编译产物只静态依赖操作系统自带的 `KERNEL32.dll` 与 `msvcrt.dll`,不需要另装微软 VC++ 运行库。
[此贴子已经被作者于2026-9-19 05:28编辑过]










