跳到主要内容

数组编组

规范性: 一维向量数组(szarray)、多维数组(mdarray)及 byte[] 在 Lua 与 C# 之间的编组规则。
相关: 类型表、创建、#get/set../02-TYPE-SYSTEM.md §数组;zlua.to_bytes / to_table../05-LIB.md;class ByObj 基础 → 06-CLASS.md[LuaMarshalAs]02-MARSHAL-AS.md

平台原则: Mono 与 Il2Cpp 的 Lua 可见语义一致;数组实例为 ByObjUserData(引用类型,走 ObjectRegistry / GCHandle 路径)。


1. 默认编组矩阵

未标注 [LuaMarshalAs] 时:

C# 类型C# → LuaLua → C#说明
T[](szarray)ByObjUserDataByObjUserData 数组形态 Lua table见 §2、§3
T[,…](mdarray)ByObjUserData ByObjUserData 接受 table
byte[]同 szarray同 szarray除非 [LuaMarshalAs(Bytes)] → ↔ Lua string(§6)

数组实例统一 Push 为 ByObjUserDataObjectUserData + 数组 ByObj 实例元表;载荷为 Il2CppArray* / 托管数组引用)。脚本侧经 get / set#arrGetValue / SetValue 等访问,见 ../02-TYPE-SYSTEM.md


2. C# → Lua

规则
形态ByObjUserData(full userdata + 数组 IMT)
nullnil
元素 Push按元素类型 T 的默认 marshal(基元 → integer/number;引用类型 → userdata;enum → integer/number)
[LuaMarshalAs(Bytes)] on byte[]Push Lua string(原始 octet 序列,非 UTF-8 文本语义)
[LuaMarshalAs(OpaqueValue)]Push OpaqueValue(仅 C#→Lua);见 04-OPAQUE.md
params T[] 返回值 / 形参(C#→Lua)与 szarray 相同:Push ByObjUserData 默认 Push table);ParamsTable 例外见 02-MARSHAL-AS.md

3. Lua → C#(szarray)

接受下列形态 二选一(外加 nil):

实参形态Pop 行为
ByObjUserData绑定类型须与目标 T[] 一致(或元素类型兼容);读数组引用传入形参
Lua table(数组形态)1n 连续整数、无空洞;按顺序 Pop 各元素为 T,构造 T[n]
nil引用类型数组 → C# null

3.1 table 形态约束

02-MARSHAL-AS.md 中顺序 table 规则相同:

接受拒绝
{ v1, v2, … },键 1..n 连续稀疏 table
空表 {}T[0](零长度数组)字符串键 table
0 起标 伪数组(v1 兼容)
非整型键

Pop 各元素时按 T 的默认 marshal 规则(含 enum integer、嵌套 szarray 的 table 或 userdata 等)。

3.2 示例

-- ByObjUserData
CS.Demo.Process(arr)

-- table → T[n]
CS.Demo.Process({ 1, 2, 3 })
CS.Demo.Process({}) -- T[0]

-- null
CS.Demo.Process(nil)

4. Lua → C#(mdarray)

实参Pop 行为
ByObjUserData绑定类型须匹配目标 mdarray
nilnull
Lua table不接受
其它luaL_error

不因 [LuaMarshalAs] 标注而接受 table(UserData 与默认等价;OpaqueValue 仅 C#→Lua)。


5. 数组元素读写(与编组的关系)

数组 实例 为 ByObjUserData;元素 读写走元素类型 marshal,不经整数组 Pop/Push:

API说明
arr:get(i1, …) / arr:set(i1, …, value)下标为 C# 各维下标(szarray 默认 0 基);返回/接受 元素类型 T 的 Lua 形态
GetValue / SetValue仍可用;GetValue 返回 object(装箱)
#arrszarray → Length;mdarray → 各维长度之积

详见 ../02-TYPE-SYSTEM.md 数组章节。

zlua.to_table 的下标差异: to_table 产出 1 基 Lua 表(t[i]arr[i-1]);get/set 使用 C# 下标


6. byte[][LuaMarshalAs(Bytes)]

配置C# ↔ Lua
默认T[] szarray(ByObjUserData;Lua→C# 亦可 table)
[LuaMarshalAs(Bytes)]强制 C# byte[] ↔ Lua string(octet 序列)

标注 Bytes 时:

方向规则
C# → LuaPush Lua string
Lua → C#Pop 须为 string不接受 ByObjUserData / table

若标注于 string 形参/返回值,则走 byte[] ↔ string 的对偶规则(按声明类型解析)。


7. params T[] 形参

params T[] 编组规则与 §1.2 szarray 相同(ByObjUserData 或 table);差异在 Lua 传参形态与空/null 语义。详见 02-MARSHAL-AS.md §ParamsTable。

要点摘要:

传入C# 收到
ByObjUserData该数组引用
table {}T[0]
table { … }按元素构造的 T[n]
nilnull 空数组)

Lua 不支持 C# 式多槽隐式收集(Sum(1, 2, 3) 非法);须 单个 实参占据 params 位。

[LuaInvoke] / delegate bridge 上的 params 不支持;见 09-FUNCTION.md


8. zlua.to_bytes / zlua.to_table

../05-LIB.md 提供的 szarray 辅助转换(不改变默认 Pop/Push 规则,仅便利 API)。

8.1 zlua.to_bytes

zlua.to_bytes(szarray) → string
约束说明
输入 szarray userdata(不支持 mdarray)
元素类型blittable 基元 白名单:boolbytesbytecharshortushortintuintlongulongfloatdouble
布局按 C# 下标 0 .. Length-1 顺序拼接; 长度头;平台原生字节序(通常 little-endian)
bool1 字节0 / 非 0
local bytes = zlua.to_bytes(int_arr) -- #bytes == #int_arr * 4(int 为 4 字节)

元素类型不在白名单 → luaL_error

Native: __zlua_to_bytes

8.2 zlua.to_table

zlua.to_table(szarray) → table
约束说明
输入 szarray userdata
元素类型无限制;每个元素按默认 marshal 转为 Lua 值
输出等长表;键 1 .. nn = #szarray
下标t[i] ↔ C# arr[i - 1](Lua 1 基 ↔ C# 0 基)
local t = zlua.to_table(obj_arr)
-- t[1] 对应 arr[0]

引用类型元素 → userdata;struct 元素 → 对应 struct marshal 形态。

Native: __zlua_to_table

8.3 与 Pop table 路径的区别

zlua.to_tableLua→C# Pop table
方向数组 userdata → Lua 表(只读转换)Lua 表 → 构造 T[n] 传入 C#
用途脚本遍历、序列化方法形参 / 返回值
约束输入须为 szarray userdata须满足 §3.1 数组形态约束

9. 数组类型构造(类型表)

Lua 侧 CSharp[...] 直接解析 int[];须:

local int_arr_type = zlua.make_szarray_type(zlua.types.int32)
local md_type = zlua.make_mdarray_type(zlua.types.int32, 2)

实例创建:

local arr = zlua.new_szarray_by_element_type(zlua.types.int32, 10)
local matrix = zlua.new_mdarray_by_spec(zlua.types.int32, { 0, 0 }, { 2, 3 })

详见 ../02-TYPE-SYSTEM.md../05-LIB.md


10. ref / out / in 数组形参

路径规则
Lua → C#03-BYREF.md06-CLASS.md §5:共享引用;无 rebind
C# → Lua[LuaInvoke] / delegate bridge)默认 OpaqueValue;见 04-OPAQUE.md

可变数组 原地修改(ref int[] 改元素)→ Lua 侧 可见ref arr = otherArray 不回写 Lua 变量。


11. Mono / Il2Cpp 一致性

要求
szarray Push / PopByObjUserData;table 规则一致
mdarray Pop仅 ByObjUserData
to_bytes / to_table语义一致
Bytes 标注两平台一致
错误消息一致或等价

12. 相关文档

文档内容
06-CLASS.mdByObjUserData、门面、ref 引用类型
02-MARSHAL-AS.mdBytesParamsTableOpaqueValue
03-BYREF.mdref / out / in
../02-TYPE-SYSTEM.md数组类型表、get/set#
../05-LIB.mdmake_szarray_typeto_bytesto_table