之前分析了UnLua的实现
南京周润发:UnLua解析(一)Object绑定luazhuanlan.zhihu.com这些内容着重于使用UE4反射实现,UnLua也支持静态绑定,可以作为反射机制的补充,扩展更多功能。UnLua静态导出实现中使用了很多C++11和模板技术,因此看起来不太直观,本文也没有深入太多细节,只从总体实现上进行解析。
宏展开
静态导出使用C++宏实现,不能轻易看出实现细节,因此我们先通过一个把宏展开的例子,来看UnLua到底做了什么。
static const luaL_Reg UObjectLib[] =
{
{
"Load", UObject_Load },
{
"IsValid", UObject_IsValid },
{
"GetName", UObject_GetName },
{
"GetOuter", UObject_GetOuter },
{
"GetClass", UObject_GetClass },
{
"GetWorld", UObject_GetWorld },
{
"IsA", UObject_IsA },
{
"Destroy", UObject_Destroy },
{
"__eq", UObject_Identical },
{
"__gc", UObject_Delete },
{
nullptr, nullptr }
};
UObjectLib数组定义了一些导出到lua的方法,看起来是lua原生导出C模块方法,没什么特别的。
最下面几个宏实现了导出,逐个分析一下。
首先是BEGIN_EXPORT_REFLECTED_CLASS(UObject),定义会转到BEGIN_EXPORT_CLASS_EX宏,这是一个通用的Class导出实现。这里bIsReflected为true,Name和Type为UObject,其余都为空。
#define BEGIN_EXPORT_CLASS_EX(bIsReflected, Name, Suffix, Type, SuperTypeName, ...)
struct FExported##Name##Suffix##Helper
{
typedef Type ClassType;
static FExported##Name##Suffix##Helper StaticInstance;
UnLua::TExportedClass<bIsReflected, Type, ##__VA_ARGS__> *ExportedClass;
~FExported##Name##Suffix##Helper()
{
delete ExportedClass;
}
FExported##Name##Suffix##Helper()
: ExportedClass(nullptr)
{
UnLua::TExportedClass<bIsReflected, Type, ##__VA_ARGS__> *Class = (UnLua::TExportedClass<bIsReflected, Type, ##__VA_ARGS__>*)UnLua::FindExportedClass(#Name);
if (!Class)
{
ExportedClass = new UnLua::TExportedClass<bIsReflected, Type, ##__VA_ARGS__>(#Name, SuperTypeName);
UnLua::ExportClass((UnLua::IExportedClass*)ExportedClass);
Class = ExportedClass;
}
可以看到定义了一个struct,宏展开后名称为FExportedUObjectHelper,内部包含静态类型StaticInstance和TExportedClass类型属性ExportedClass,然后是析构函数与一半构造函数。构造函数中会创建TExportedClass类型变量ExportedClass,并执行ExportClas函数进行导出,内部具体细节下面再分析。
然后看ADD_LIB(UObjectLib)
#define ADD_LIB(Lib)
Class->AddLib(Lib);
很简单,像是往ExportedClass里注册函数。
之后是END_EXPORTED_CLASS()
#define END_EXPORT_CLASS(...)
}
};
用于结束构造函数和类定义
最后是IMPLEMENT_EXPORTED_CLASS
#define IMPLEMENT_EXPORTED_CLASS(Name)
FExported##Name##Helper FExported##Name##Helper::StaticInstance;
用于创建静态变量StaticInstance
类结构
这里看下unlua实现静态导出所用类结构,可以先了解这些概念,不用细究实现细节。
首先是实现C++类型静态导出的类,比如上面看到的TExportedClass类,相关结构如下:
IExportedClass
属于interface,静态导出类都要继承它,里面定义了Register,AddLib等基本接口。
TExportedClassBase
实现了IExportedClass的接口,属于基本静态导出类,实现可注册类和导出lua原生C模块功能
成员:
FString Name
Fname ClassName
TArray<IExportedProperty*> Properties 导出的属性
Tarray<IExportedFunction*> Functions 导出的方法
Tarray<IExportedFunction*> GlueFunctions 导出的胶水方法
接口:
AddLib():添加lua原生C模块
Register():注册自己和相关函数