UnLua相关
UnLua相关
UnLua相关
C++ 怎么导出类给Lua
不导出能调用吗
- 反射系统动态导出
怎么编写自己的C++业务封装给Lua
- 工具函数和常规写c库的的方式一样
- 库函数注册流程
EXPORT_UNTYPED_CLASS
、IMPLEMENT_EXPORTED_CLASS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
namespace {
template<typename ViewType>
int32 UI_GetWidgetFromName(lua_State* L)
{
int32 NumParams = lua_gettop(L);
if (NumParams != 2)
{
UNLUA_LOGERROR(L, LogUnLua, Log, TEXT("%s: Invalid parameters!"), ANSI_TO_TCHAR(__FUNCTION__));
return 0;
}
ViewType* View = Cast<ViewType>(UnLua::GetUObject(L, 1));
const char* WidgetName = lua_tostring(L, 2);
UWidget* Widget = View->GetWidgetFromName(WidgetName);
UnLua::PushUObject(L, Widget);
return 1;
}
}
class MiscUtils {};
static const luaL_Reg MiscUtilsLib[] =
{
{ "GetWidgetFromName", UI_GetWidgetFromName<UUserWidget> },
{ nullptr, nullptr }
};
EXPORT_UNTYPED_CLASS(MiscUtils, false, MiscUtilsLib)
IMPLEMENT_EXPORTED_CLASS(MiscUtils)
初始化流程
Lua_State
依托于 IModuleInterface 的生命周期初始化
依托于 引擎的事件回调 执行 env 清理
1 2 3 4 5 6 7 8 9 10 11 12 13
class FUnLuaModule : public IModuleInterface { public: virtual void StartupModule() override { FLuaContext::Create(); GLuaCxt->RegisterDelegates(); } virtual void ShutdownModule() override { } };
Lua脚本静态绑定
监听 UObject的引擎事件
FUObjectArray::FUObjectCreateListener
FUObjectArray::FUObjectDeleteListener
执行 Lua脚本的绑定
1 2 3 4 5 6 7 8 9 10 11 12
bool FLuaEnv::TryBind(UObject* Object) { // ... UFunction* Func = Class->FindFunctionByName(FName("GetModuleName")); // ... FString ModuleName; UObject* CDO = bIsCDO ? Object : Class->GetDefaultObject(); CDO->ProcessEvent(Func, &ModuleName); // ... return GetManager()->Bind(Object, *ModuleName, GLuaDynamicBinding.InitializerTableRef); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
bool UUnLuaManager::Bind(UObject *Object, const TCHAR *InModuleName, int32 InitializerTableRef) { // ... UnLua::FLuaRetValues RetValues = UnLua::Call(L, "require", TCHAR_TO_UTF8(InModuleName)); // require Lua module // ... if (!RetValues.IsValid() || RetValues.Num() == 0) { Error = "invalid return value of require()"; bSuccess = false; } else if (RetValues[0].GetType() != LUA_TTABLE) { Error = FString("table needed but got "); if(RetValues[0].GetType() == LUA_TSTRING) Error += UTF8_TO_TCHAR(RetValues[0].Value<const char*>()); else Error += UTF8_TO_TCHAR(lua_typename(L, RetValues[0].GetType())); bSuccess = false; } else { bSuccess = BindInternal(Class, InModuleName, bMultipleLuaBind, Error); // bind!!! } if (bSuccess) { FString RealModuleName = *ModuleNames.Find(Class); // create a Lua instance for this UObject Env->GetObjectRegistry()->Bind(Object, TCHAR_TO_UTF8(*RealModuleName)); // try call user first user function handler int32 FunctionRef = PushFunction(L, Object, "Initialize"); // push hard coded Lua function 'Initialize' if (FunctionRef != LUA_NOREF) { if (InitializerTableRef != LUA_NOREF) { lua_rawgeti(L, LUA_REGISTRYINDEX, InitializerTableRef); // push a initializer table if necessary } else { lua_pushnil(L); } bool bResult = ::CallFunction(L, 2, 0); // call 'Initialize' if (!bResult) { UE_LOG(LogUnLua, Warning, TEXT("Failed to call 'Initialize' function!")); } luaL_unref(L, LUA_REGISTRYINDEX, FunctionRef); } else { UE_LOG(LogUnLua, Warning, TEXT("Failed to attach %s module for object %s,%p!\n%s"), InModuleName, *Object->GetName(), Object, *Error); } return bSuccess; }
Lua文件的加载是如何控制的
- Unlua_2.2.2 - LuaEnv.cpp
1
2
3
4
5
6
7
8
9
10
FLuaEnv::FLuaEnv()
{
// ...
AddSearcher(LoadFromCustomLoader, 2);
AddSearcher(LoadFromFileSystem, 3);
AddSearcher(LoadFromBuiltinLibs, 4);
// ...
}
NewObject的Lua扩展
- LoadObject
- LoadClasss
- NewObject
https://github.com/Tencent/UnLua/blob/master/Plugins/UnLua/Source/UnLua/Private/UELib.cpp
本文由作者按照 CC BY 4.0 进行授权