跳到主要内容

C# 调用 Lua

ZLua 用 [LuaInvoke](L/Invoke)从 C# 调用 Lua 函数,用法类比 P/Invoke:声明 static extern,编译期由 CodeGen 注入真实实现。

Canonical 示例:zlua-demo/Assets/Bootstrap.cs

概述

  • module — Lua 模块名,传给 LoadLuaModule
  • method — 模块 return { ... } 表中的键名
  • Editor 与 Player 声明方式相同;底层 Mono 走 RunLuaFunc,Il2Cpp 走 InternalCall + C++ 桥

基本用法

无返回值

[LuaInvoke("app", "main")]
private static extern void AppMain();

带参数与返回值

[LuaInvoke("app", "add")]
private static extern int AppAdd(int a, int b);

void Start()
{
int sum = AppAdd(10, 20); // Lua: return a + b
}

Lua 侧(app.lua):

local function add(a, b)
return a + b
end

return {
main = main,
add = add,
}

声明规则

规则说明
必须是 static extern实例方法、普通 static 方法不可用于 LuaInvoke
不能是泛型方法也不能位于泛型类的实例成员上
module / method 与 Lua 一致[LuaInvoke("app","add")]return { add = ... }
参数 / 返回值类型遵循默认 Marshal 规则;可用 [LuaMarshalAs] 覆盖(Mono)

构造函数注入在 程序集编译后 由 Editor CodeGen(dnlib)或 Player Weaver 完成,开发者只维护 extern 声明。

Editor 与 Player 实现差异

阶段Mono (Editor)Il2Cpp (Player)
编译后dnlib 注入 → RunLuaFuncIL → InternalCall
调用路径C# 快速桥 + Lua APIC++ 模板 + 直接 lua API
开发者感知

Player MVP 对参数 / 返回值类型有限制(int、bool、string、void 等),超出可能需等 Il2Cpp 扩展。见 兼容性

模块加载约定

[LuaInvoke("app", "main")] 要求 LoadLuaModule("app") 能读到模块源码。Demo 约定:

  • Editor:{ProjectRoot}/LuaScripts/app.lua
  • Player:StreamingAssets/LuaScripts/app.lua.txt

详见 Lua 模块加载

多函数与命名空间

同一 C# 类可声明多个 [LuaInvoke],指向同一或不同模块:

[LuaInvoke("app", "main")]
private static extern void AppMain();

[LuaInvoke("battle", "tick")]
private static extern void BattleTick(float dt);

每个 module 对应独立 Lua 文件(或同一 loader 内的不同逻辑分支)。

错误排查

现象可能原因
进入 Play 无反应未调用 LuaAppDomain.Initialize
attempt to call a nil valueLua 表未导出对应函数名
返回值始终 0Lua 未 return;或 marshal 类型不匹配
Player 正常 Editor 异常检查 Editor 下 LuaScripts/*.lua 路径
Player 异常 Editor 正常未 Sync StreamingAssets;或使用了 MVP 不支持的签名

Mono / Il2Cpp 支持

能力MonoIl2Cpp
[LuaInvoke] void
多 int 参数 / int 返回
string / bool
复杂类型 / [LuaMarshalAs]
多模块

学习路径

上一篇快速开始
下一篇Lua 访问 C# 基础

相关文档