跳到主要内容

编组总览 — 默认规则矩阵

规范性: 未标注 [LuaMarshalAs](或标注为 LuaMarshalType.Default)时,各 CLR 类型在 C# ↔ Lua 双向调用中的默认编组。
覆盖: 参数、返回值、字段、属性上的 [LuaMarshalAs]02-MARSHAL-AS.md
实现:../../impl/marshal/

1. 平台原则

  • Mono(Editor)与 Il2Cpp(Player)的 Lua 可见编组语义一致;差异仅在实现层(零 GC、生成代码等),不改变脚本可观察行为。
  • 函数 / delegate: Lua 调用 C# 方法时,delegate 形参接受 Lua function,由桥接层隐式 marshal,详见 09-FUNCTION.md
  • [LuaInvoke] / delegate bridge(C# → Lua)ref/out/in 的默认 Push 为 OpaqueValue,与 Lua→C# 路径不同,见 03-BYREF.md04-OPAQUE.md

2. 默认编组矩阵

C# 类型C# → LuaLua → C#说明
boolbooleanboolean
charinteger / numberinteger / number按 Unicode 码点(16 位)
byteinteger / numberinteger / number见 §3
sbyteinteger / numberinteger / number见 §3
shortinteger / numberinteger / number见 §3
ushortinteger / numberinteger / number见 §3
intinteger / numberinteger / number见 §3
uintinteger / numberinteger / number见 §3
longinteger / numberinteger / number见 §3
ulonginteger / numberinteger / number见 §3;须落在 Lua integer 可表示范围
floatnumbernumber
doublenumbernumber
IntPtrinteger / numberinteger / number指针 数值ToInt64 / new IntPtr);与 10-POINTER.md 非托管指针 不同
UIntPtrinteger / numberinteger / number同上
nint / nuintIntPtr / UIntPtrIntPtr / UIntPtr本机整数别名
T*(非托管指针)Pointer(lightuserdata)Pointer(lightuserdata)仅透传;见 10-POINTER.md
函数指针(如 delegate*<int,int>Pointer(lightuserdata)Pointer(lightuserdata)仅透传;见 10-POINTER.md
System.TypedReferenceOpaqueValueOpaqueValue OpaqueValue;默认即此,见 10-POINTER.md04-OPAQUE.md
stringstringstring
byte[]ByObjUserDataByObjUserDatatableT[] 相同(§4);[LuaMarshalAs(Bytes)] 时改为 ↔ string,见 02-MARSHAL-AS.md
classClassUserDataClassUserData引用身份;nilnull成员门面 = 声明类型,见 06-CLASS.md
T[](一维 / szarray)ByObjUserDataByObjUserDatatable见 §4、07-ARRAY.md
T[,] 等多维(mdarray)ByObjUserDataByObjUserData见 §4;接受 Lua table
enuminteger / numberinteger / numberByObjUserData(boxed)默认 推 userdata;boxed 仅经 zlua.box;详见 08-ENUM.md
structByValUserDataOpaqueValueStructUserDataType(...) 产物C#→Lua 常规路径见 05-STRUCT.md;标注 OpaqueValueref/in/out 时为 OpaqueValue(04-OPAQUE.md)。Lua→C# 亦接受 SMT.__call 构造的 StructUserData。默认接受 table / 多栈参数;须 [LuaMarshalAs(Table | UnpackedValues)] + FieldOrPropertyNames02-MARSHAL-AS.md
DelegatefunctionDelegateUserDatafunctionDelegateUserDataC#→Lua:若 target 为 Lua 回调源则 Push function,否则 ByObjUserData;见 09-FUNCTION.md
objectClassUserDataSystem.Object 门面)boolean / number / string / userdata门面 = 声明类型 object,即使运行时是 string 等也 改走特殊编组;见 06-CLASS.md
Nullable<T>TnilTnilT 为值类型时 nilnull
interfaceClassUserData(ByObj)ClassUserData与 class 相同:门面 = 接口声明类型;亦可 [LuaMarshalAs(Table | UnpackedValues)](见 02-MARSHAL-AS.md06-CLASS.md
decimal暂不支持(默认)暂不支持(默认)v1 默认路径未纳入
ref struct(如 Span<T>05-STRUCT.md../05-LIB.md同左不能作为普通 by-val 形参默认传递
void(返回值)(无)
null / nilnilnil引用类型Nullable、delegate 等可空形态

2.1 UserData 形态说明

上表中的 ClassUserData、数组 ByObjUserData(szarray / mdarray 实例)、StructUserData、boxed enum(ByObjUserData)、DelegateUserData 均为带类型元表的 full userdatalua_newuserdata + metatable),脚本侧经 : / . 访问成员。

与下列形态 不同

形态特征文档
OpaqueValuelightuserdata, metatable04-OPAQUE.md
Pointer(非托管指针 / 函数指针)lightuserdata, metatable,仅透传10-POINTER.md

3. integer 与 number

  • Lua 5.4+:整型基元、char、枚举底层整型、IntPtr / UIntPtr 数值优先使用 integerlua_pushinteger / lua_isinteger)。
  • 不支持 integer 的 Lua 版本:退化为 number,须为整数值(无小数部分)。
  • Il2Cpp Codegen 与 Mono 反射路径的 可见语义一致;仅实现层 API 不同。

4. 数组(szarray / mdarray)

C# 类型C# → LuaLua → C#
T[](szarray)ByObjUserData(数组实例 userdata)ByObjUserData 数组形态 Lua table(见下)
T[,…](mdarray)ByObjUserData ByObjUserData
byte[]同 szarray(除非 [LuaMarshalAs(Bytes)]同 szarray

4.1 C# → Lua

数组实例统一 Push 为 ByObjUserDataObjectUserData + 数组 ByObj 实例元表;载荷为托管数组引用)。脚本侧经 GetValue / SetValue#arr(szarray)等访问,见 ../02-TYPE-SYSTEM.md07-ARRAY.md

4.2 Lua → C#(szarray)

接受下列 二选一

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

4.3 Lua → C#(mdarray)

接受 ByObjUserData接受 table。nullnil ↔ null

4.4 table 形态约束(szarray Pop)

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

  • 不接受 稀疏 table、字符串键 table、或 0 起标的伪数组(v1 兼容)。

5. 引用类型门面(摘要)

对所有 引用类型 形参、返回值、字段/属性(class / interface / object / 数组 / delegate 等):

概念含义
Identityuserdata 持有的托管对象引用(运行时实际实例)
View / 门面userdata 挂接的 IMT 与成员可见性;唯一来源 = 本次编组的声明类型

规则摘要:

  1. C# → Lua:始终按 声明类型 选择默认 marshal 形态与 ByObj IMT; 因运行时实际类型不同而改挂实际类型 mt,也 因此改走 string 等特殊编组。
  2. Downcast:仅 zlua.cast(obj, targetType)(见 ../05-LIB.md);要求目标类型可从当前门面类型赋值,返回 新 userdata(同 identity、新门面)。
  3. 对象缓存:键为 (identity, viewType);同一实例可有多个视图 userdata。

完整规则见 06-CLASS.md

6. 相关文档

主题文档
[LuaMarshalAs] 覆盖默认02-MARSHAL-AS.md
ref / in / out03-BYREF.md
OpaqueValue04-OPAQUE.md
struct05-STRUCT.md
class / interface06-CLASS.md
数组 / Bytes07-ARRAY.md
枚举08-ENUM.md
delegate / Lua function09-FUNCTION.md
指针 / 不支持类型10-POINTER.md
重载与实参匹配../04-METHOD-OVERLOAD.md
zlua.* API../05-LIB.md