跳到主要内容

值类型

enumstructNullable<T> 均为值类型相关形态。行为以 Struct MarshalEnum Marshal 为准。

需要 Table / UnpackedValues / Opaque 等少分配套路时,见 LuaMarshalAs0GC Marshal

形态对照

类型默认跨边界形态构造实例
enuminteger / number(常量) EnumType(...) / _ctor;boxed 仅用 zlua.box
structByValUserData 等(见规范)Type(...) / _default()
Nullable<T>有值同 T;无值 → Lua nil

默认 不能{ X=1, Y=2 }foo(x, y) 组装 struct 传入 C#,须 Type(...) / ByVal userdata,或显式 [LuaMarshalAs(Table|UnpackedValues)](见上)。

enum

跨边界默认就是 integer / number(类型表上的常量也是整型,不是 userdata):

local Color = CSharp.AC['MyGame.Color']
print(Color.Red) -- 整型值,非 userdata
host:SetColor(Color.Red)
host:SetColor(1) -- underlying 整型亦可

比较常量时用 integer,不要当 userdata 比。类型表 __call不要Color(...) / Color._ctor(...)

需要 boxed 枚举对象(如部分 object 形参、数组槽位等)时,只用 zlua.box

local boxed = zlua.box(Color, Color.Red)
local boxed2 = zlua.box(Color, 2)
print(zlua.unbox(boxed)) -- underlying integer

细则见 Enum Marshal

struct

local Point2D = CSharp.AC['MyGame.Point2D']
local origin = Point2D._default()
local p = Point2D(3, 4)
p.X = 10
p.Y = 20
传递C# 形参行为
userdata(如 Point2D(...)by-val Point2D拷贝
userdata(同型)ref / out / in Point2D真 ref,可写回

静态成员经类型表访问;struct 无继承ref struct 不作普通 by-val。

Nullable<T>

  • C# null(无值)↔ Lua nil
  • 有值时按底层 T 的规则 Marshal
  • 不要给非 Nullable 的值类型传 nil

完整示例(示意)

namespace MyGame
{
public enum Team { None = 0, Red = 1, Blue = 2 }

public struct Vec2
{
public float X, Y;
public Vec2(float x, float y) { X = x; Y = y; }
public static float Dot(Vec2 a, Vec2 b) => a.X * b.X + a.Y * b.Y;
}
}
local Team = CSharp.AC['MyGame.Team']
local Vec2 = CSharp.AC['MyGame.Vec2']
print(Team.Red)
print(Vec2.Dot(Vec2(1, 0), Vec2(0, 1)))

常见错误

现象处理
enum 当 userdata 比较失败用 integer 比较
Color(...) / Color._ctor 失败enum 类型表构造;传整型,或 zlua.box
struct 修改未回写by-val 拷贝;对 ref 形参传入同型 userdata(Type(...))或走 Opaque
{X=,Y=} 传入未标注的 structTable(见 LuaMarshalAs),或先 Type(...)
foo(x,y) 传入未标注的 structUnpackedValues(见 0GC Marshal
ref struct 作 by-val不支持

学习路径

上一篇C# 调用 Lua
下一篇Function 与 Delegate

相关文档