闲鱼技术01 发表于 2022-9-26 08:22

xLua 随笔

一、纯lua相关问题

0. Lua 的 元表 元方法 和 opp的关系

Lua 学习元表,元方法_liaosheng:)-CSDN博客_lua 元方法
这个博客写的很详细了,多注意:元表的含义, 和__index这个元方法的含义;
Lua本没有面向对象,但是利用元表和__index的特效我们也可以实现面向对象。
BaseClass = { trans = nil }

function BaseClass:new() -- 基类构造函数
    local o = {}
    setmetatable(o, { __index = self })
    return o
end

-----------------------------------------------
ItemClass = BaseClass:new()

function ItemClass:Release()
    print("释放")
end

-----------------------------------------------
Fruit = ItemClass:new()

function Fruit:BeEaten()
    print("水果被吃")
end

-----------------------------------------------
function start()
    local f = Fruit:new()

    f:BeEaten()
    f:Release()
end1. Lua 的 虚变量

“_”即为虚变量,用来承接一些多个返回值的方法中不被我们需要的返回值,
功能上可以理解为占位符,但是虚变量是有值的。
2. Lua 的 虚表(听上去和虚变量有关联,其实完全不是一个东西)

先大白话总结:
Lua有自己的GC机制,被引用的对象不会被GC回收,
但是被弱引用引用的对象可以被回收,虚表(也叫弱表)就是具有弱引用条目的表。
所以到底是什么呢:
虚表也是表,设置了元表,同时定义了__mode字段:
      例:
local x = {}
setmetatable( x, {__mode="v"} )__mode字段取值可分为k / v / kv
k表示table的keys是weak的,可被回收;
v表示table的values是weak的,可被回收;
kv表示都weak,key和value中的一个被回收,那么kv键值对就被从表中移除。
二、xLua使用遇到问题

1. require的使用

官方示例中: local util = require 'xlua.util'
直接获取 Resources/xlua/util.lua 脚本,喔,原来 require 直接会从Resources下面找脚本???
那么如果想获取的脚本不在 Resources 目录下怎么办呢?
顺藤摸瓜,于是在官方示例里找到了这些:
                AddSearcher(StaticLuaCallbacks.LoadBuiltinLib, 2); // just after the preload searcher
                AddSearcher(StaticLuaCallbacks.LoadFromCustomLoaders, 3);
#if !XLUA_GENERAL
                AddSearcher(StaticLuaCallbacks.LoadFromResource, 4);
                AddSearcher(StaticLuaCallbacks.LoadFromStreamingAssetsPath, -1);
#endif从这段代码就知道了:为什么可以从Resources下可以找到 你想要的脚本
internal static int LoadFromResource(RealStatePtr L)
      {
            try
            {
                string filename = LuaAPI.lua_tostring(L, 1).Replace('.', '/') + ".lua";

                // Load with Unity3D resources
                UnityEngine.TextAsset file = (UnityEngine.TextAsset)UnityEngine.Resources.Load(filename);
                if (file == null)
                {
                  LuaAPI.lua_pushstring(L, string.Format(
                        "\n\tno such resource '{0}'", filename));
                }
                else
                {
                  if (LuaAPI.xluaL_loadbuffer(L, file.bytes, file.bytes.Length, "@" + filename) != 0)
                  {
                        return LuaAPI.luaL_error(L, String.Format("error loading module {0} from resource, {1}",
                            LuaAPI.lua_tostring(L, 1), LuaAPI.lua_tostring(L, -1)));
                  }
                }

                return 1;
            }
            catch (System.Exception e)
            {
                return LuaAPI.luaL_error(L, "c# exception in LoadFromResource:" + e);
            }
      }回到原本的问题,自定义添加require该怎么办呢?
看上面第一个代码块中四个 AddSearcher ,
第一个LoadBuiltinLib,推测是内置的函数blablabla的,有时间可以试试把它注释掉,康康哪些方法用不了了.... 噗
第三个第四个都眼熟,resources 和 streamingAssets。
还剩第二个LoadFromCustomLoaders,追进去!
internal static int LoadFromCustomLoaders(RealStatePtr L)
      {
            try
            {
                string filename = LuaAPI.lua_tostring(L, 1);

                LuaEnv self = ObjectTranslatorPool.Instance.Find(L).luaEnv;

                foreach (var loader in self.customLoaders)
                {
                  string real_file_path = filename;
                  byte[] bytes = loader(ref real_file_path);
                  if (bytes != null)
                  {
                        if (LuaAPI.xluaL_loadbuffer(L, bytes, bytes.Length, "@" + real_file_path) != 0)
                        {
                            return LuaAPI.luaL_error(L, String.Format("error loading module {0} from CustomLoader, {1}",
                              LuaAPI.lua_tostring(L, 1), LuaAPI.lua_tostring(L, -1)));
                        }
                        return 1;
                  }
                }
                LuaAPI.lua_pushstring(L, string.Format(
                  "\n\tno such file '{0}' in CustomLoaders!", filename));
                return 1;
            }
            catch (System.Exception e)
            {
                return LuaAPI.luaL_error(L, "c# exception in LoadFromCustomLoaders:" + e);
            }
      }嗯,就是它了!customLoaders!
然后blablabla,就找到了这个AddLoader(CustomLoader xxx)这个方法。
传入的是一个 委托:
其定义为:public delegate byte[] CustomLoader(ref string filepath);
喔,在这里处理你传入的path和想要怎么处理,然后返回脚本的 byte[]
okay,搞定!
上官方示例:
LuaEnv luaenv = new LuaEnv();
#if UNITY_EDITOR
            luaenv.AddLoader(new SignatureLoader(PUBLIC_KEY, (ref string filepath) =>
            {
                filepath = Application.dataPath + "/XLua/Examples/10_SignatureLoader/" + filepath.Replace('.', '/') + ".lua";
                if (File.Exists(filepath))
                {
                  return File.ReadAllBytes(filepath);
                }
                else
                {
                  return null;
                }
            }));----------------------------------------------------------------------------------------------------------------------------
好吧,我直接看了半天官方示例,但是没有提前看最开始的文档,我是xx....
文档上明明白白写着设置loader的方法,哈哈哈
页: [1]
查看完整版本: xLua 随笔