-- 共享库一览 —— 用 **Lua** 把四个共享库各叫一遍 -- Shared libraries tour -- calling all four shared libraries from **Lua** -- -- ◆ 这份例程在练什么 -- ◆ What this example exercises -- -- 共享库是**一次投入、22 门语言都受益**的那种东西:`regex`(正则)· `dbf`(dBASE 数据文件) -- · `sql`(跑在 .dbf 上的查询)· `turtle`(海龟作图)。它们**不是 Lua 的库**, -- 而是每一门语言都能调的同一份实现 —— 这份例程就是"从 Lua 这边调得动"的活证据。 -- The shared libraries are one investment serving all 22 languages: `regex`, `dbf` (dBASE data -- files), `sql` (queries over .dbf) and `turtle`. They are not Lua libraries -- they are one -- implementation every language can call. This example is the living proof that Lua can. -- -- regex : 模式 `abc` 在 `xxabcyy` 里**找得到**吗(1 = 找得到) -- dbf : 现建一张两字段的表、塞两条记录,再看一眼记录数 -- sql : 在刚建的那张表上跑一句 `SELECT ... WHERE` -- turtle : 抬笔走 50 步,看它的坐标(不写屏幕,所以**不需要开窗口**) -- -- ◆ 为什么全程只调"返回整数"的那些接口 -- ◆ Why only the integer-returning calls -- -- Lua 的字符串**不可变** ⇒ 传不出一个可写缓冲区,而 `dbf_get` / `sql_cell` 这类要调用方 -- 给 dst。所以这里走另一条路:**需要缓冲区的地方用 `alloc()` 自己拿一块地址** -- (见下面建记录那几句),取值一律用"只问长度"的形态(`dbf_fname(h, f, 0)`)。 -- Lua strings are immutable, so there is no writable buffer to hand to `dbf_get`/`sql_cell`. -- Two ways around it: take an address yourself with `alloc()` (see the record-building lines), -- and use the "length only" form of the accessors (`dbf_fname(h, f, 0)`). -- -- ⚠ 跑一次会在**本文件所在目录**建一个 `libdemo.dbf`(这就是 dbf 那一半在演示的事)。 -- ⚠ Running this creates a small `libdemo.dbf` **next to this file** -- that is the point of it. -- ── regex:模式匹配 ── print_str("REGEX_HIT=") println_int(re_test("abc", "xxabcyy")) print_str("REGEX_MISS=") println_int(re_test("abc", "xxabxyy")) print_str("REGEX_VALID=") println_int(re_is_valid("(a|b)+")) -- ── dbf:建表 → 塞两条 → 读记录数 ── -- 字段类型用**字符的字节值**:'C' = 67(字符型)· 'N' = 78(数字型)—— -- Lua 没有字符字面量,所以这里直接写数字。 h = dbf_new("libdemo.dbf") dbf_addfield(h, "NAME", 67, 8, 0) dbf_addfield(h, "AGE", 78, 3, 0) dbf_build(h) rec = alloc(64) dbf_mkrec(h, rec) dbf_put(h, rec, 0, "Alice") dbf_put(h, rec, 1, "30") dbf_add(h, rec) dbf_mkrec(h, rec) dbf_put(h, rec, 0, "Bob") dbf_put(h, rec, 1, "7") dbf_add(h, rec) dbf_flush(h) print_str("DBF_ROWS=") println_int(dbf_records(h)) print_str("DBF_FIELDS=") println_int(dbf_fields(h)) print_str("DBF_FIELD0_LEN=") println_int(dbf_fname(h, 0, 0)) dbf_close(h) -- ── sql:在刚建的表上查 ── print_str("SQL_ROWS=") println_int(sql_run("libdemo.dbf", "SELECT * FROM t WHERE AGE > 20")) print_str("SQL_COLS=") println_int(sql_cols()) print_str("SQL_COL0_LEN=") println_int(sql_colname(0, 0)) -- ── turtle:抬笔走 50 步(落笔会去画屏幕,那要窗口)── turtle_reset() turtle_pen_up() turtle_forward(50) print_str("TURTLE_X=") println_int(turtle_x()) print_str("TURTLE_Y=") println_int(turtle_y()) -- ── sed:sed 的替换规则(s / y 两条命令,依附 regex 库)—— 缓冲区那一半只有 C 拿得到, -- 这里压的是「只问长度」那一支(cap 传 0)与对账用的 sed_count。 print_str("SED_COUNT=") println_int(sed_count("s/a/X/g", "banana")) print_str("SED_LEN=") println_int(sed_sub("s/a/X/g", "banana", 0, 0)) print_str("DONE=") println_int(1) -- 期望(scripts/lib-examples-check.sh 按这一行比对): -- EXPECT: REGEX_HIT=1|REGEX_MISS=0|REGEX_VALID=1|DBF_ROWS=2|DBF_FIELDS=2|DBF_FIELD0_LEN=4|SQL_ROWS=1|SQL_COLS=2|SQL_COL0_LEN=4|TURTLE_X=0|TURTLE_Y=50|SED_COUNT=3|SED_LEN=6|DONE=1