Darp.Luau 0.2.0

dotnet add package Darp.Luau --version 0.2.0
                    
NuGet\Install-Package Darp.Luau -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Darp.Luau" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Darp.Luau" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Darp.Luau" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Darp.Luau --version 0.2.0
                    
#r "nuget: Darp.Luau, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Darp.Luau@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Darp.Luau&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Darp.Luau&version=0.2.0
                    
Install as a Cake Tool

Darp.Luau

Darp.Results Downloads License .NET

Darp.Luau is a .NET wrapper around Luau focused on native AOT compatibility, typed value access, and explicit ownership for Luau-backed references.

Why another lua library

  • NativeAOT first
  • Typed reads and writes for tables, functions, userdata, strings, and buffers
  • Clear lifetime guarantees both stability and performance
  • Simple API through source-generated interceptors
  • Custom libraries and managed userdata
  • Support for linux,windows,macos on both x64,arm64

Quick start

using Darp.Luau;

using var lua = new LuauState();

using LuauFunction log = lua.CreateFunction((string message) => Console.WriteLine(message));
lua.Globals.Set("log", log);

using LuauTable config = lua.CreateTable();
config.Set("name", "Ada");
config.Set("enabled", true);
lua.Globals.Set("config", config);

lua.Load(
    """
    function add(a, b)
      return a + b
    end

    log(config.name)
    result = add(20, 22)
    """
).Execute();

double result = lua.Globals.GetNumber("result");

Call Lua functions from C#

using LuauFunction add = lua.Globals.GetLuauFunction("add");
double sum = add.Invoke<double>(1, 2);

using LuauFunction pair = lua.Globals.GetLuauFunction("pair");
(int total, int delta) = pair.Invoke<int, int>(20, 4);

Invoke<TR>(...) converts a single Luau return value to the managed type you ask for and ignores extras. Use Invoke<TR1, TR2>(...), ... for typed multi-return calls, and InvokeMulti(...) for raw LuauValue[] access. The current argument buffer accepts up to 4 arguments per call.

Load(...).Execute(...) follows the same return-shaping pattern for chunk execution: use Load(...).Execute<TR>() for the first typed return value, Load(...).Execute<TR1, TR2>(), ... for typed multi-return calls, and Load(...).ExecuteMulti() for raw LuauValue[] access.

(int total, int delta) = lua.Load("return 20, 4").Execute<int, int>();

Expose managed callbacks

Use CreateFunction(...) for supported fixed delegate signatures:

using LuauFunction sum = lua.CreateFunction((int a, int b) => a + b);
lua.Globals.Set("sum", sum);

using LuauFunction pair = lua.CreateFunction((int a, int b) => (a + b, a - b));
lua.Globals.Set("pair", pair);

Use CreateFunctionBuilder(...) when you need manual argument parsing, explicit user-facing errors, or a callback shape that the generator-backed path does not support:

using LuauFunction pair = lua.CreateFunctionBuilder(static args =>
{
    if (!args.TryValidateArgumentCount(2, out string? error))
        return LuauReturn.Error(error);
    if (!args.TryReadNumber(1, out int a, out error) || !args.TryReadNumber(2, out int b, out error))
        return LuauReturn.Error(error);
    if (a <= b)
        return LuauReturn.Error("Expected a to be greater than b");

    return LuauReturn.Ok(a + b, a - b);
});

CreateFunction(...) must be called directly at the call site so the generator can intercept it. It supports fixed delegate signatures, including supported top-level tuple returns. If you need a shape that is not supported there, use CreateFunctionBuilder(...).

Work with tables

using LuauTable settings = lua.CreateTable();
settings.Set("volume", 0.8);
settings.Set("muted", false);
settings.Set("blob", new byte[] { 1, 2, 3 });

lua.Globals.Set("settings", settings);

using LuauTable roundTripped = lua.Globals.GetLuauTable("settings");
double volume = roundTripped.GetNumber("volume");
bool muted = roundTripped.GetBoolean("muted");
byte[] blob = roundTripped.GetBuffer("blob");

Use Get* for required values, TryGet* for optional or external data, and *OrNil when nil is part of the contract.

Work with userdata

var player = new PlayerUserdata { Name = "Ada" };

lua.Globals.Set("player", IntoLuau.FromUserdata(player));

PlayerUserdata samePlayer = lua.Globals.GetUserdata<PlayerUserdata>("player");

using LuauUserdata playerRef = lua.Globals.GetLuauUserdata("player");
_ = playerRef.TryGetManaged(out PlayerUserdata? resolvedPlayer, out string? error);

Managed userdata types implement ILuauUserData<T> to expose script-facing fields, setters, and methods. See Userdata for the full hook model.

CreateFunction(...) also supports managed userdata parameters and returns for types that implement ILuauUserData<TSelf>.

Register custom libraries

lua.OpenLibrary("game", static (state, in LuauTable lib) =>
{
    lib.Set("answer", 42);

    using LuauFunction add = state.CreateFunction((int a, int b) => a + b);
    lib.Set("add", add);
});

OpenLibrary(...) registers a global table. It is a convenient way to expose host-provided APIs, but it is not a require(...)-style module loader by itself.

Ownership and lifetime

  • LuauTable, LuauFunction, LuauString, LuauBuffer, LuauUserdata, and reference-backed LuauValue are owned references and should be disposed.
  • LuauTableView, LuauFunctionView, LuauStringView, LuauBufferView, LuauUserdataView, and LuauArgs are borrowed callback-scoped values.
  • Reference-backed values belong to one LuauState; cross-state usage is invalid.

Current boundaries

  • Load(...).Execute(...) is the script execution API today. If you want file-based execution, read the file yourself and pass its contents in.
  • CreateFunction(...) is generator-backed and has no runtime fallback.
  • LuauState is not thread-safe.
  • A documented module system and higher-level async/thread orchestration are not part of the current surface yet.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 93 3/24/2026
0.1.1 95 3/16/2026
0.1.0 94 3/16/2026