Skip to main content

Function and Delegate

PathSyntaxNotes
Lua → C# parameterobj:Foo(function(...) end)Implicit ReadDelegate
C# → Lua (callback slot)handler(...)May be a function or DelegateUserData; always use call syntax
C# fetches Lua by nameGetFunction<T>(mod, name)See C# calling Lua

Authoritative: Function Marshal, to_delegate.

1. Lua function as a C# parameter

public void RegisterCallback(System.Action<int> onValue)
{
onValue?.Invoke(42);
}
host:RegisterCallback(function(v)
print("callback:", v)
end)

Day to day you do not need to write to_delegate by hand: a closed delegate is created automatically from the parameter’s delegate type.

Lua argumentResult
functionCreated from the parameter type
nilnull
Existing delegate userdataPassed through
OtherType error

You can also hang callbacks on properties:

logic.Combine = function(a, b) return a + b end
print(logic:Run(3, 5))

2. C# callbacks into Lua

Callback slots retrieved from C# always use call syntax:

local handler = host:GetHandler()
handler(42)
Slot sourcetype(handler)Notes
Native C# delegateuserdata (__call)handler(...) is enough
Lua function passed through C# and backfunctionStill a Lua function, not a delegate

So do not rely on handler:Invoke(...): it does not work on functions, and it conflicts with the “round-trip stays a function” design. Details: 09-FUNCTION.

warning

Native open delegates (target == null) are not supported today.

3. When to use GetFunction / to_delegate

ScenarioApproach
Known module + method name + concrete TGetFunction<T>
Lua already has a function; need a specific delegate typezlua.to_delegate(fn, closedDelegateType)
C# parameter is already a concrete Action/FuncPass function directly

The second argument to to_delegate must be a closed type (e.g. Action<int>), not an open generic.

4. Event and lifetime

  • Events use add_ / remove_ (see Lua calling C#)
  • Unsubscribe must use the same function reference
  • Multicast keeps multicast semantics; Lua functions are held via registry refs—avoid C# holding a delegate long-term while destroying the Lua environment

Common mistakes

SymptomCause
expects delegate XNeither function nor delegate
Callback never runsC# never Invoke’d; or GetFunction result discarded without caching
Wrong to_delegate typeSecond arg is not a closed delegate type
remove has no effectNot the same function reference

Learning path

PreviousValue types
NextArrays