|
相关文章:
之前介绍的UObject,UStruct传递都是单个元素传递,slua也支持array和map的容器传递。
LuaArray
UE中数组类型为TArray,把TArray从UE传到lua,会用一个LuaArray类把TArray包装起来,LuaArray也提供了迭代接口供lua使用数组常用操作。
TArray传到Lua时有两种创建LuaArray方式,一种会把TArray复制一份,Lua中对LuaArray操作不会影响C++TArray,另一种是把TArray引用传到Lua。Lua对LuaArray的添加和删除会影响C++的TArray。
复制一份
当TArray作为函数的返回值时,会复制一份,相关代码如下:
构造函数接受两个参数,分别为数组元素的UProperty,和源array数据。- LuaArray::LuaArray(UProperty* p, FScriptArray* buf)
- : inner(p)
- , prop(nullptr)
- , propObj(nullptr)
- {
- array = new FScriptArray();
- clone(array, p, buf);
- }
复制代码- void LuaArray::clone(FScriptArray* destArray, UProperty* p, const FScriptArray* srcArray) {
- // blueprint stack will destroy the TArray
- // so deep-copy construct FScriptArray
- // it's very expensive
- if(!srcArray || srcArray->Num()==0)
- return;
-
- FScriptArrayHelper helper = FScriptArrayHelper::CreateHelperFormInnerProperty(p,destArray);
- helper.AddValues(srcArray->Num());
- uint8* dest = helper.GetRawPtr(;
- uint8* src = (uint8*)srcArray->GetData();
- for(int n=0;n<srcArray->Num();n++) {
- p->CopySingleValue(dest,src);
- dest+=p->ElementSize;
- src+=p->ElementSize;
- }
- }
复制代码 源array类型为FScriptArray,可以认为是一个数组,通过遍历FScriptArray可以把元素逐个复制到luaarray的array属性中。因为我们已经知道了数组内元素的UProperty类型,因此可用对应的CopySingleValue方法利用反射机制来拷贝元素。
传递引用
把UObject上的TArray属性进行传递时,会使用传递引用的方式。LuaArray构造函数中,并没有创建新的FScriptArray,而是把Tarray的指针赋给了array,因此Lua中操作的就是TArray本身,对LuaArray的add和remove操作都会影响到实际的TArray。- LuaArray::LuaArray(UArrayProperty* p, UObject* obj)
- : inner(p->Inner)
- , prop(p)
- , propObj(obj)
- {
- array = prop->ContainerPtrToValuePtr<FScriptArray>(obj);
- }
复制代码
数组迭代
LuaArray实现了基本的add,remove,迭代等功能,前面的相对简单,主要介绍下迭代功能。
Lua中,可以通过for in pairs语法遍历LuaArray中的元素:- for i,v in pairs(arr) do
- print(&#34;arr item&#34;,i,v)
- end
复制代码 slua提供了LuaArray::Enumerator类作为迭代器,LuaArray::Enumerable作为迭代函数,来实现pairs功能,迭代函数内容如下:- int LuaArray::Enumerable(lua_State* L) {
- CheckUD(LuaArray::Enumerator, L, 1);
- auto arr = UD->arr;
- if (arr->isValidIndex(UD->index)) {
- auto element = arr->inner;
- auto es = element->ElementSize;
- auto parms = ((uint8*)arr->array->GetData()) + UD->index * es;
- LuaObject::push(L, UD->index);
- LuaObject::push(L, element, parms);
- UD->index += 1;
- return 2;
- }
- return 0;
- }
复制代码 UD就是Enumerator,index为当前遍历到的下标,根据下标和数组,直接去ScriptArray对应的内存偏移取元素指针,返回给lua。
LuaArray与GC
LuaArray会对内部的元素产生引用,UEGC会看到这些引用,当LuaArray销毁,这些引用也会消失。因为LuaArray继承自FGCObject,内部实现了AddReferencedObjects()函数,每次UE执行GC时,都会调用这个函数。函数内部通过之前介绍的LuaReference方法,模拟一遍UE的引用添加逻辑。
LuaMap
LuaMap与LuaArray的实现思想基本相同,也实现了Map的add,remove等常用功能,最大的区别可能是LuaMap底层数据为ScriptMap散列表,这也使LuaMap在一些处理上要小心对待。
如下图所示,ScriptArray和ScriptMap都存储了3个元素,容器中也都留有空位。对于ScriptArray,做clone、迭代等操作时只要遍历前三个位置即可,也不需要判断前三个位置元素是否有效,因为它们肯定是有效的。而ScriptMap由于是散列表,因此clone、迭代时必须把整个容器都遍历一遍,还有判断当前元素是否有效,过滤掉空的槽位。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|