1.1 Lua与C++的交互机制是什么?如何在Lua中调用UE API?
★★★ 困难考点: Lua C API、绑定原理、内存管理
参考答案:
Lua与C++通过栈交换数据,所有交互都经过
lua_State*:- 压入值:
lua_pushinteger/lua_pushstring/lua_pushboolean; - 取值:
lua_tointeger/lua_tostring(负数下标从栈顶开始,-1 为栈顶); - 调用 Lua 函数:
lua_getglobal取函数 →lua_pushinteger压参 →lua_pcall(L, 1, 1, 0)→lua_tointeger(L, -1)取返回值。
- 压入值:
UE 绑定原理:C++ 类注册到 Lua 使用 metatable + userdata:
luaL_newmetatable创建元表;- 将
__index设为元表自身,使表查找能命中已注册方法; - 用
luaL_Reg注册方法,方法内通过lua_touserdata(L, 1)取回 C++ 对象指针(self); - 用
luaL_setfuncs批量绑定方法。
void BindMyClass(lua_State* L)
{
luaL_newmetatable(L, "MyClass");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_Reg methods[] = {
{"GetName", [](lua_State* L) -> int {
AMyActor* Self = (AMyActor*)lua_touserdata(L, 1);
lua_pushstring(L, *Self->GetName());
return 1;
}},
{NULL, NULL}
};
luaL_setfuncs(L, methods, 0);
lua_pop(L, 1);
}- 内存管理:UE 对象被 GC 后 Lua 侧引用需失效:
- 用弱引用表(
__mode设为"v"弱值)存 UE 对象,对象被回收时 Lua 侧条目自动失效; - C++ 侧用
TWeakObjectPtr防止悬空引用。
- 用弱引用表(
lua_newtable(L); // 弱引用表
lua_newtable(L); // metatable
lua_pushstring(L, "__mode");
lua_pushstring(L, "v"); // 弱值
lua_settable(L, -3);
lua_setmetatable(L, -2);- 易错点:userdata 与 lightuserdata 的区别(后者不参与 GC);
lua_pcall返回值 0 表示成功,非 0 为错误码,需配合错误处理函数。