Table of Contents

Scripting with Lua

Embed a Lua engine in your host, expose C# values to scripts, and read results back.

What you'll build

A console host that registers the IScriptEngineService (SquidStd.Scripting.Lua) through the SquidStd bootstrap, runs a small Lua script, and prints values evaluated by the engine.

Prerequisites

  • .NET 10 SDK
  • dotnet add package SquidStd.Scripting.Lua
  • dotnet add package SquidStd.Services.Core
  • dotnet add package SquidStd.Generators

Steps

1. Register the Lua engine

The engine needs a LuaEngineConfig (it watches a scripts directory) and is started by the bootstrap as a SquidStd service. The DirectoriesConfig it depends on is already registered by the core services. The generated script-module registration call adds any [RegisterScriptModule] modules before startup.


var scriptsDirectory = Path.Combine(AppContext.BaseDirectory, "scripts");
Directory.CreateDirectory(scriptsDirectory);

bootstrap.ConfigureServices(
    container =>
    {
        var engineConfig = new LuaEngineConfig(
            AppContext.BaseDirectory,
            scriptsDirectory,
            "SquidStd.Samples.ScriptingLua",
            "1.0.0"
        );

        container.RegisterInstance(engineConfig);
        container.RegisterStdService<IScriptEngineService, LuaScriptEngineService>();
        container.RegisterGeneratedScriptModules();

        return container;
    }
);

2. Run a script and read results

RegisterGlobal exposes a C# value under an exact name, ExecuteScript runs Lua code, and ExecuteFunction evaluates an expression and returns a ScriptResult whose Data holds the value.


var engine = bootstrap.Resolve<IScriptEngineService>();
var stats = ((LuaScriptEngineService)engine).GetStats();

engine.RegisterGlobal("greeting", "hello from C#");
engine.ExecuteScript("result = greeting .. ' and lua'");

var sum = engine.ExecuteFunction("3 + 4");
var message = engine.ExecuteFunction("result");

Console.WriteLine($"lua modules = {stats.ModuleCount}");
Console.WriteLine($"3 + 4 = {sum.Data}");
Console.WriteLine($"result = {message.Data}");

3. Define a generated module

[RegisterScriptModule] opts the type into source generation. [ScriptModule("sample")] is still the runtime Lua metadata used as the module name.


[RegisterScriptModule, ScriptModule("sample")]
internal sealed class SampleLuaModule { }

Run it

dotnet run --project samples/SquidStd.Samples.ScriptingLua

Prints:

lua modules = 1
3 + 4 = 7
result = hello from C# and lua

How it works

IScriptEngineService wraps a MoonSharp Script. Registering it with RegisterStdService lets the bootstrap call its StartAsync during StartAsync, which wires up modules, constants, and a file watcher over the configured scripts directory. Globals you register become Lua variables, and ExecuteFunction evaluates a return <expression> and surfaces the value through ScriptResult.Data.

See also