xLua 核心 API 全解析从 C# 调用 Lua 到类型映射与内置宏【免费下载链接】xLuaxLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc.项目地址: https://gitcode.com/gh_mirrors/xl/xLua导读本文以 xLua 官方 API 参考文档XLua_API_EN.md为主线系统讲解 xLua 的 C# 侧核心 APILuaEnv、LuaTable、LuaFunction、Lua 侧访问 C# 对象的语法CS.命名空间、uint64、xlua.*工具函数、cast、C# 与 Lua 的类型映射规则以及三个重要的编译期宏。读完本文你将掌握在 Unity/.NET 工程中用 xLua 执行 Lua 代码、读写 Lua 数据、调用 Lua 函数、在 Lua 中操作 C# 对象并正确选择值类型传递与避免装箱开销的完整实战方案。文章同时结合仓库源码LuaEnv.cs、LuaTable.cs、LuaFunction.cs、StaticLuaCallbacks.cs 等对 API 的底层实现与调用链进行佐证方便读者按图索骥深入阅读。一、C# 侧核心 APIxLua 的 C# 侧 API 围绕三个核心类型展开LuaEnvLua 虚拟机环境的封装、LuaTableLua 表的封装、LuaFunctionLua 函数的封装。以下 API 的签名与行为均以 XLua_API_EN.md 为准并结合源码实现说明底层细节。1.1 LuaEnv 类型虚拟机生命周期管理LuaEnv是 xLua 中最顶层的类型一个实例对应一个独立的 Lua 运行时环境。其核心成员在源码 LuaEnv.cs 中均有对应实现。object[] DoString(string chunk, string chunkName chunk, LuaTable env null)功能执行一段 Lua 代码块。参数chunkLua 代码字符串chunkName出错时用于调试信息定位指明错误发生在哪个代码块的哪一行env该代码块的执行环境环境变量表。返回值代码块中return语句的返回值。例如代码块return 1, helloDoString返回的数组将包含两个对象一个是double类型的1另一个是字符串hello。示例LuaEnv luaenv new LuaEnv(); object[] ret luaenv.DoString(print(hello)\r\nreturn 1); UnityEngine.Debug.Log(ret ret[0]); luaenv.Dispose();源码印证在 LuaEnv.cs 中DoString(string ...)先将字符串按 UTF-8 编码为字节数组再转调DoString(byte[] ...)字节数组版本内部依次执行xluaL_loadbuffer加载字节码/源码、lua_pcall保护模式调用成功后将栈顶的LUA_MULTRET多返回值通过translator.popValues弹出为object[]。env参数通过lua_setfenv设置为该 chunk 的环境。T LoadStringT(string chunk, string chunkName chunk, LuaTable env null)功能加载编译一段代码块但不执行返回代表该代码块的委托delegate或LuaFunction。参数与DoString相同T必须是委托类型或LuaFunction。返回值代表该代码块的委托或LuaFunction类型实例。源码印证LuaEnv.cs 中LoadStringT首先校验T必须是LuaFunction或Delegate的子类否则抛出InvalidOperationException然后同样走xluaL_loadbuffer加载 chunk经translator.GetObject转换为目标委托类型。仓库还提供了LoadString(byte[] chunk, ...)重载与直接返回LuaFunction的便捷重载适合加载预编译的 Lua 字节码。LuaTable Global功能代表 Lua 全局环境_G的LuaTable。源码印证LuaEnv.cs 中Global属性直接返回内部维护的_G字段可借助它读写全局变量。void Tick()功能清理未被手动释放的 Lua 侧LuaBase对象如LuaTable、LuaFunction等需要在MonoBehaviour的Update中等周期性地调用。源码印证LuaEnv.cs 中Tick()从refQueue队列中逐条取出GCAction并调用translator.ReleaseLuaBase释放 Lua 引用在非XLUA_GENERAL即 Unity 环境下还会通过translator.objects.Check对 C# 对象进行有效性检查默认每 tick 最多检查 20 个对象用于检测已销毁的UnityEngine.Object避免悬空引用。void AddLoader(CustomLoader loader)功能添加自定义 loader加载器。当 Lua 中执行require需要某个文件时注册的 loader 会被回调。参数loader是委托类型byte[] CustomLoader(ref string filepath)。loader 找到文件后将其读入内存并以字节数组返回如果需要支持调试定位应把filepath设置为 IDE 可以找到的路径相对或绝对。源码印证委托定义于 LuaEnv.csAddLoader内部调用AddSearcher将 loader 插入到package.loadersLua 5.3 为package.searchers的加载器链表中从而参与require的查找流程。void Dispose()功能销毁该LuaEnv实例释放 Lua 虚拟机相关资源。LuaEnv 使用建议原文强调全局只使用一个实例在Update中调用 GC 方法Tick不再需要时调用Dispose。1.2 LuaTable 类型Lua 表的 C# 封装LuaTable的底层实现位于 LuaTable.cs它继承自LuaBase内部通过lua_getref/lua_gettop等 Lua C API 与虚拟机交互并提供了“无装箱no boxing”的泛型版本读写接口。T GetT(string key)功能读取key对应的值并转换为类型T若键不存在或类型不匹配返回null。注意在 LuaTable.cs 中若取到nil且TValue是值类型会抛出InvalidCastException提示can not assign nil to ...因此读取值类型字段前需确保 Lua 侧确实存在该键。T GetInPathT(string path)功能与Get的区别在于会解析路径中的.。例如var i tbl.GetInPathint(a.b.c)等价于执行 Lua 代码i tbl.a.b.c。避免多次调用Get与获取中间变量执行效率更高。源码印证LuaTable.cs 中GetInPath调用xlua_pgettable_bypath这一原生扩展接口一次调用完成多层路径的查表。void SetInPathT(string path, T val)功能GetInPathT对应的 setter按路径设置嵌套字段的值。源码印证LuaTable.cs 中通过xlua_psettable_bypath一次完成多层路径赋值。void GetTKey, TValue(TKey key, out TValue value)功能上面 API 的 key 只支持string本 API 对 key 类型无此限制可使用任意类型作为键out参数接收取出的值。源码印证LuaTable.cs 中GetTKey, TValue通过translator.PushByType压入任意类型的 key再调用xlua_pgettable完成取表。void SetTKey, TValue(TKey key, TValue value)功能GetTKey, TValue对应的 setter。源码印证LuaTable.cs 中通过xlua_psettable完成赋值出错时抛出让调用方能感知的 Lua 异常。T CastT()功能将表转换为类型T。T可以是声明了CSharpCallLua的接口、带默认构造函数的类型或结构体、Dictionary、List等。源码印证LuaTable.cs 中CastT通过translator.GetObject将 Lua 栈上的 table 转换为目标 C# 类型。void SetMetaTable(LuaTable metaTable)功能为表设置 metatable元表。补充配合 LuaTable.cs 中的GetMetaTable可读写元表用于自定义表的__index、__call等行为。1.3 LuaFunction 类型Lua 函数的 C# 封装性能提示原文强调通过LuaFunction访问 Lua 函数存在装箱/拆箱开销。若需要频繁调用不建议使用该类型推荐用table.GetABCDelegate获取 C# 委托后再调用假设ABCDelegate是 C# 委托类型。使用table.GetABCDelegate之前需将ABCDelegate加入生成代码列表详见 custom_generate.md。object[] Call(params object[] args)功能以可变参数调用 Lua 函数返回调用的返回值数组。源码印证LuaFunction.cs 中转调Call(args, null)核心实现通过lua_pcall执行函数translator.popValues弹出所有返回值。object[] Call(object[] args, Type[] returnTypes)功能调用 Lua 函数并显式指定每个返回值的类型系统按指定类型自动转换。源码印证LuaFunction.cs 中若returnTypes非空则popValues(L, oldTop, returnTypes)按类型数组逐项转换返回值。void SetEnv(LuaTable env)功能等价于 Lua 的setfenv函数为函数设置新的环境表。源码印证LuaFunction.cs 中通过lua_setfenv实现可用于构造沙箱环境。二、Lua 侧访问 C# 对象CS APIxLua 在 Lua 侧提供了CS全局命名空间用于直接访问 C# 类型与成员。相关回调注册于 ObjectTranslator.cs 的OpenLib方法以及 StaticLuaCallbacks.cs 中。2.1 类型构造、静态成员与枚举CS.namespace.class(...)调用 C# 类型构造函数返回实例local v1 CS.UnityEngine.Vector3(1, 1, 1)CS.namespace.class.field访问 C# 静态成员print(CS.UnityEngine.Vector3.one)CS.namespace.enum.field访问枚举值-- 例如CS.UnityEngine.KeyCode.A、CS.UnityEngine.TextAnchor.MiddleCenter 等2.2typeof函数类似 C# 的typeof关键字返回Type对象。典型场景是GameObject.AddComponent这类需要Type参数的重载newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))2.3 无符号 64 位整数支持uint64Lua 5.3 的整数类型为有符号 64 位无法直接完整表达ulong。xLua 为此提供了uint64工具表其实现依赖 LuaDLL.cs 中的lua_pushuint64、lua_touint64、lua_isuint64等原生接口并在 ObjectCasters.cs 中为ulong注册了专用类型检查器既接受普通 number也接受 uint64 userdata。可用的函数如下| 函数 | 功能 | | - | - | |uint64.tostring| 无符号数转字符串 | |uint64.divide| 无符号数除法 | |uint64.compare| 无符号比较相等返回 0大于返回正数小于返回负数 | |uint64.remainder| 无符号取模 | |uint64.parse| 字符串转无符号数 |2.4xlua.structclone克隆一个 C# 结构体struct。由于 struct 是值类型直接赋值可能共享引用尤其当结构体内部含引用类型字段时需要显式克隆时使用此函数local newStruct xlua.structclone(oldStruct)2.5xlua.private_accessible(class)使某个 C# 类型的私有字段、属性、方法在 Lua 侧可访问。当需要绕过 C# 的private修饰符进行测试或反射式访问时非常有用。底层实现在 StaticLuaCallbacks.csXLuaPrivateAccessible回调若找不到对应 C# 类型会返回 Lua 错误xlua.private_accessible, can not find c# type。2.6cast函数以指定接口访问对象适用于实现类型不可访问如 internal 类型的场景。假设calc对象实现了 C# 的PerformentTest.ICalc接口cast(calc, typeof(CS.PerformentTest.ICalc))调用后即可通过该接口成员操作对象。cast由ObjectTranslator.OpenLib中注册的castFunction实现出错时抛出c# exception in xlua.cast: ...见 StaticLuaCallbacks.cs。2.7 像表一样操作 C# 对象访问 C# 对象如同访问 Lua 表调用函数如同调用 Lua 函数甚至可以直接使用运算符调用 C# 的运算符重载。官方示例local v1 CS.UnityEngine.Vector3(1, 1, 1) local v2 CS.UnityEngine.Vector3(1, 1, 1) v1.x 100 v2.y 100 print(v1, v2) local v3 v1 v2 print(v1.x, v2.x) print(CS.UnityEngine.Vector3.one) print(CS.UnityEngine.Vector3.Distance(v1, v2))三、C# 与 Lua 类型映射3.1 基本数据类型映射| C# 类型 | Lua 类型 | | - | - | |sbyte,byte,short,ushort,int,uint,double,char,float|number| |decimal|userdata| |long,ulong|userdata/lua_IntegerLua 5.3 | |byte[]|string| |bool|boolean| |string|string|其中long/ulong在 Lua 5.3 下可映射到lua_Integer64 位有符号整数而ulong超出有符号范围的场景则走userdata配合上文uint64工具表使用。相关 push/take 逻辑在 ObjectTranslator.cs 与 ObjectCasters.cs 中有完整注册表。3.2 复杂数据类型映射| C# 类型 | Lua 类型 | | - | - | |LuaTable|table| |LuaFunction|function| | class 或 struct 实例 |userdata、table| | method、delegate |function|LuaTable若 C# 方法入参或 Lua 方法返回值指定为LuaTable类型则 Lua 侧必须是table若 C# 未指定类型Lua 中的table会被转换为LuaTable。LuaFunction同理指定LuaFunction时 Lua 侧必须是function未指定类型时 Lua 函数转换为LuaFunction。LuaUserData对应非 C# 托管对象的 Lua userdata。class 或 struct 实例C# 传入的类或结构体实例映射为 Lua userdata通过__index访问其成员。若 C# 指定了入参类型Lua 侧直接使用该类型实例的 userdata若该类型带默认构造函数Lua 中的table会被自动转换——转换规则为调用构造函数构造实例将 table 中与字段同名的键一一赋值给 C# 的对应 setter 成员。method 与 delegate成员方法与委托都对应 Lua 函数。C# 的普通参数与引用参数对应 Lua 函数参数C# 的返回值对应 Lua 的第一个返回值C# 的引用参数ref与out参数按顺序对应 Lua 的第 2 至第 N 个返回值。四、编译期宏Macros宏在 Unity 的 Player Settings → Scripting Define Symbols 中配置直接影响 xLua 源码的编译行为| 宏 | 作用 | | - | - | |HOTFIX_ENABLE| 启用热补丁hotfix功能。在源码 Hotfix.cs、DelegateBridge.cs 以及生成模板 LuaDelegateBridge.tpl.txt 中均以该宏作为功能开关。 | |NOT_GEN_WARNING| 存在反射未生成代码的调用路径时打印警告。 | |GEN_CODE_MINIMIZE| 以最小化代码段的方式生成代码。该宏在 Generator.cs 中控制生成代码的裁剪策略用于减小生成代码体积。 |五、实战组合示例与最佳实践结合上文 API给出一个同时覆盖 C# 侧与 Lua 侧完整链路的示例// 1. 创建全局唯一的 LuaEnv LuaEnv luaenv new LuaEnv(); // 2. 注册自定义 loader使 require 能加载自定义路径的脚本 luaenv.AddLoader((ref string filepath) { string path Assets/MyLua/ filepath.Replace(., /) .lua.txt; return System.IO.File.Exists(path) ? System.IO.File.ReadAllBytes(path) : null; }); // 3. 执行 Lua 代码并接收返回值 object[] ret luaenv.DoString( local t { name xlua, version 3 } return t ); LuaTable t ret[0] as LuaTable; Debug.Log(t.Getstring(name)); // 输出 xlua Debug.Log(t.GetInPathint(version)); // 输出 3 // 4. 加载函数并通过委托高频调用避免 LuaFunction 装箱开销 var func luaenv.LoadStringSystem.Funcint, int, int(return function(a, b) return a b end); Debug.Log(func(1, 2)); // 输出 3 // 5. 每帧 Tick 清理未手动释放的 LuaBase 对象 void Update() { luaenv.Tick(); } // 6. 不再使用时销毁 void OnDestroy() { luaenv.Dispose(); }关键实践要点单例优先全局只创建一个LuaEnv实例避免多虚拟机带来的内存与同步开销。周期性 GC在Update中调用Tick()让未手动释放的LuaTable/LuaFunction被及时回收。委托替代 LuaFunction高频调用路径使用table.GetDelegate或LoadStringDelegate并把委托类型加入 custom_generate.md 所述的生成代码列表规避装箱/拆箱。路径读取用 GetInPath/SetInPath嵌套表访问用GetInPathT替代多次Get减少跨语言调用次数。类型映射牢记于心byte[]↔ Luastring、long/ulong在 Lua 5.3 下的映射差异以及ref/out参数出现在 Lua 侧返回值序列中的规则是排查跨语言参数错位问题的关键。如需进一步了解热补丁、生成代码配置与 FAQ可继续阅读仓库中的 hotfix.md、configure.md 与 faq.md。【免费下载链接】xLuaxLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc.项目地址: https://gitcode.com/gh_mirrors/xl/xLua创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
IronClaw Telegram 扩展的 remove_reaction 能力:全量清除语义与结果契约解析 人工智能AI 应用交互助手AI Agent 【免费下载链接】ironclaw IronClaw is an Agent OS focused on privacy, security and extensibility 项目地址: https://gitcode.com/gh_mirrors/iro/ironclaw 点击查看 免费下载 本文围绕 IronClaw 开源仓库中 Telegram 扩展包… · 2026/9/24 17:18:46
2026年国产研发管理工具选型指南:Gitee替代Jira的深度评估 1. 研发管理工具选型的底层逻辑与市场格局1.1 为什么“替代 Jira”在 2026 年成为必答题做研发管理的同行这两年应该都有明显感受:团队里讨论“要不要换掉 Jira”的频率越来越高。原因不复杂,我把它拆成三层来看。第一层是成本与合规。Jira 的 Server 版… · 2026/9/24 18:23:27
AI需求分析如何简化PRD文档工作:从口述到结构化需求 做了这么多年需求分析,我最大的感受不是“需求到底怎么做”,而是大部分时间都花在了文档整理这种低价值工作上。业务在微信里语音说一堆,产品经理开会记几页白板,研发那边却等着看一份像样的PRD——这一层转换成本,几乎… · 2026/9/24 18:23:27
网络约束与排放约束下的输电网风电协调优化实践 让我们先从最熟悉的一个场景说起:风电大发的时候,电网却不敢让它满发。调度员看着风电预测曲线一路走高,只能一边叹气一边下指令“压出力”,因为送出线路的热稳定极限已经快到头了。如果你只把这当成“线路装不下”,那… · 2026/9/24 18:23:27
视频去字幕技术全解析:AI涂抹修复与VSR开源方案实战 视频去字幕这件事,我前前后后折腾了差不多两年。最早是帮一个做跨境电商的朋友处理产品视频,原素材是从供应商那里拿的,画面上压着硕大的中文字幕和品牌水印,直接发到海外平台既违和又影响观感。后来自己做内容,从录屏… · 2026/9/24 18:23:27
Docker Compose多文件合并:规则、实践与避坑指南 这个写 docker-compose 的系列到了第10篇,前面聊过镜像、网络、卷、环境变量、容器启动顺序,今天专门聊文件属性里的合并。为什么要单独拎出来讲?因为我发现很多人一旦开始用多文件部署 prometheusgrafana、elasticsearch、ollama 这类组合&a… · 2026/9/24 18:23:27
VisionPro二次开发:C#通讯模块从架构到实战的完整指南 1. 为什么视觉程序里最费时间的往往是通讯模块——先把架构想清楚做了几年VisionPro二开,有个很深的感触:很多刚入门的朋友以为视觉项目里最难的是那些图像处理工具——找轴承缺珠用什么算法、引脚偏移怎么卡阈值、焊锡反光怎么打光。真正在产线上跑过几… · 2026/9/24 18:23:14
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44