Skip to main content

LuaMarshalAs

Overrides default Marshal rules for bidirectional C# ↔ Lua calls. Applied to parameters, return values, methods, or fields.

using ZLua;

public void SendRaw([LuaMarshalAs(LuaMarshalType.Bytes)] byte[] data) { }

[return: LuaMarshalAs(LuaMarshalType.OpaqueLightUserData)]
public Point2D GetPointOnStack() { ... }

Type Definitions

public enum LuaMarshalType
{
Default,
UserData,
Bytes,
OpaqueLightUserData,
}

[Flags]
public enum LuaMarshalFlags
{
None = 0,
OptionalField = 1, // missing key OK when assembling struct from table
}

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue
| AttributeTargets.Method | AttributeTargets.Field)]
public sealed class LuaMarshalAsAttribute : Attribute
{
public LuaMarshalType LuaMarshalType { get; }
public LuaMarshalFlags Flags { get; set; }
public LuaMarshalAsAttribute(LuaMarshalType luaMarshalType = LuaMarshalType.Default);
}

LuaMarshalType

ValueDirectionEffect
DefaultBothUse Marshal cheatsheet defaults
UserDataBothForce full userdata (instead of default boolean/number/string, etc.)
BytesBothbyte[] ↔ Lua string (raw octets, not UTF-8 text semantics)
OpaqueLightUserDataC# → Lua onlyPush lightuserdata temp token (StructStackScope handle); use in the sync chain or upgrade via zlua.to_user_data

Default is legal for all types. Below are values that may be annotated explicitly besides Default:

C# TypeLegal LuaMarshalType
Primitives (bool, char, integers, float/double)UserData
IntPtr / UIntPtr / nint / nuintUserData
stringUserData, Bytes
byte[]Bytes, UserData
T[] / multidimensional arraysUserData
enumUserData
structUserData, OpaqueLightUserData (latter C#→Lua only)
class / interface / Delegate / objectUserData
Nullable<T>Same legal set as T
Unmanaged pointers, function pointers, TypedReference, decimal, ref structDefault only (or type unsupported)

Direction filter: OpaqueLightUserData on a pure Lua→C# parameter is illegal; Editor falls back to Default and logs an error.

Full rules: LuaMarshalAs spec.

Illegal Annotation Behavior

BehaviorDescription
MarshalSilently fall back to Default; call continues
Editor log[ZLua] Invalid LuaMarshalAs: ... falling back to Default
PlayerNo log; still falls back to Default

Examples

byte[] as Lua string

public void Upload([LuaMarshalAs(LuaMarshalType.Bytes)] byte[] payload) { }
Upload("\001\002\003") -- Lua string as byte sequence

Force enum userdata

public void SetColor([LuaMarshalAs(LuaMarshalType.UserData)] Color c) { }
local c = CSharp.AC['MyGame.Color'].Red
SetColor(c)

C#→Lua on-stack struct temporary handle

[return: LuaMarshalAs(LuaMarshalType.OpaqueLightUserData)]
public Point2D GetPointHandle() { ... }
local opaque = GetPointHandle() -- lightuserdata, valid in sync chain
local ud = zlua.to_user_data(opaque) -- upgrade to StructUserData

Resolution Priority

For a single parameter / return value:

  1. [LuaMarshalAs] on the parameter / return value
  2. Method-level [LuaMarshalAs] (covers the whole method unless overridden by a finer annotation)
  3. Default

Mono / Il2Cpp Support

RuntimeSupport
Mono (Editor)
Il2Cpp (Player)