xlua - c#访问lua table

公共代码

public class Test2 : MonoBehaviour
{
    private LuaEnv m_LuaEnv;

    void Start()
    {
        m_LuaEnv = new LuaEnv();
        m_LuaEnv.AddLoader((ref string filePath) =>
        {
            filePath = filePath.Replace('.', '/');
            filePath = $"Assets/{filePath}.lua.txt";
            var txtAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(filePath);
            return Encoding.UTF8.GetBytes(txtAsset.text);
        });

        m_LuaEnv.DoString("require('Lua.Test2')");

        //逻辑代码...
    }

    void OnDestroy()
    {
        if (null != m_LuaEnv)
        {
            m_LuaEnv.Dispose();
        }
    }

}

 

1, 将table映射为class或struct

lua脚本:Assets/Lua/Test2.lua.txt

myPerson = { name = "zhangsan", gender = "male" }

 

类型定义(c#)

public class MyPerson1
{
    public string name;
    public int age;
    private string gender;

    public string GetGender() { return gender; }
}

public struct MyPerson2
{
    public string name;
    public int age;
    private string gender;

    public string GetGender() { return gender; }
}

table映射为c#对象

MyPerson1 person1;
m_LuaEnv.Global.Get("myPerson", out person1); //映射为class, 只有public属性会被赋值
Debug.Log($"{person1.name}, {person1.age}, {person1.GetGender()}");

MyPerson2 person2;
m_LuaEnv.Global.Get("myPerson", out person2); //映射为struct
Debug.Log($"{person2.name}, {person2.age}, {person2.GetGender()}");

 

 

2, 将table映射为c# interface

注意:需要加上 [CSharpCallLua],然后生成代码,否则会报异常。代码生成的时候,会生成一个接口的实现类(就是lua虚拟机交互代码)

[CSharpCallLua]
public interface MyInterface
{
    int Add(int a, int b); //映射lua对象的Add函数

    event EventHandler<int> OnAddInvoke; //映射lua对象的add_OnAddInvoke和remove_OnAddInvoke函数

    int Num { get; set; } //映射lua对象的Num属性

    object this[int index] { get; set; } //映射lua对象的get_Item和set_Item函数
}


[CSharpCallLua]
public delegate MyInterface MyInterface_New(int num); //委托用于映射lua的new函数

生成的代码类似下面这样

 

lua脚本:Assets/Lua/Test2.lua.txt

MyInterfaceImpl = {}
MyInterfaceImpl.__index = MyInterfaceImpl


function MyInterfaceImpl.new(n)
    local obj = {}
    setmetatable(obj, MyInterfaceImpl)
    obj:ctor(n)
    return obj
end


function MyInterfaceImpl:ctor(n)
    self.Num = n or 0
    self.m_List = {}
    self.m_OnAddInvokeListeners = {}
end


function MyInterfaceImpl:Add(a, b)
    local result = a + b
    for i, v_delegate in ipairs(self.m_OnAddInvokeListeners) do
        v_delegate(self, result)
    end
    return result
end


function MyInterfaceImpl:get_Item(index)
    return self.m_List[index]
end

function MyInterfaceImpl:set_Item(index, v)
    self.m_List[index] = v
end


function MyInterfaceImpl:add_OnAddInvoke(delegate)
    table.insert(self.m_OnAddInvokeListeners, delegate)
end

function MyInterfaceImpl:remove_OnAddInvoke(delegate)
    for i, v in ipairs(self.m_OnAddInvokeListeners) do
        if CS.System.Object.Equals(self.m_OnAddInvokeListeners[i], delegate) then
            table.remove(self.m_OnAddInvokeListeners, i)
            break
        end
    end
end

table映射为c#接口

var newDelegate = m_LuaEnv.Global.GetInPath<MyInterface_New>("MyInterfaceImpl.new");
var impl = newDelegate(2);
Debug.Log($"Num: {impl.Num}");

impl.OnAddInvoke += OnAddInvokeNotify;
Debug.Log($"Add: {impl.Add(1, 2)}");
impl.OnAddInvoke -= OnAddInvokeNotify;
Debug.Log($"Add: {impl.Add(5, 6)}");

impl.Num = 5;
Debug.Log($"Num: {impl.Num}");

impl[0] = "one";
Debug.Log($"[0]: {impl[0]}");

 

 

3, 直接获取LuaTable

不需要生成代码,但性能很慢,且没有类型检查,不建议使用。

var luaTable = m_LuaEnv.Global.Get<LuaTable>("MyInterfaceImpl");var luaFuncNew = luaTable.Get<LuaFunction>("new");
luaFuncNew.Action(new Action<object, int>(OnAddInvokeNotify));
var luaTableImpl = luaFuncNew.Func<int, LuaTable>(2);
Debug.Log($"Num: {luaTableImpl.Get<int>("Num")}");

luaTableImpl.Get<LuaFunction>("add_OnAddInvoke").Action(luaTableImpl, new Action<object, int>(OnAddInvokeNotify));
Debug.Log($"Add: {luaTableImpl.Get<LuaFunction>("Add").Call(luaTableImpl, 1, 2)[0]}");
luaTableImpl.Get<LuaFunction>("remove_OnAddInvoke").Action(luaTableImpl, new Action<object, int>(OnAddInvokeNotify));
Debug.Log($"Add: {luaTableImpl.Get<LuaFunction>("Add").Call(luaTableImpl, 5, 6)[0]}");
luaTableImpl.Set("Num", 5);
Debug.Log($"Num: {impl.Num}");

luaTableImpl.Get<LuaFunction>("set_Item").Call(luaTableImpl, 0, "one");
Debug.Log($"[0]: {luaTableImpl.Get<LuaFunction>("get_Item").Func<LuaTable, int, string>(luaTableImpl, 0)}");

 

posted @ 2024-02-28 22:34  yanghui01  阅读(63)  评论(0编辑  收藏  举报