Xlua 和 c# 之间 gc 的原理

先说重点

  • 这里是我输入给 chatgpt 的关键词
这里是我输入给gpt的关键词:
帮我生成一个mk的备忘录, 主要是讲清楚c#与lua之间的引用关系和原理以整个过程. 里面主要包括三个方面
1. c#引用lua对象时, c#侧luatable在调用Get<T>初始化方法时, 会在lua注册表(强引用表, luaL_ref(L, LUA_REGISTRYINDEX) )中增加对应table或function的引用计数, 保证lua侧不被gc, 最后在c#侧Dispose对象, 最后在lua侧走gc回收
2. lua引用c#对象时, c#侧会缓存入栈给lua的对象, 返回实际索引给lua, lua用弱表缓存(__mode = v)这个c#对象, 只要没有别的lua对象引用这个c#对象时, lua在gc时会走到原表里的__gc方法, 告诉c#这个对象lua不再使用, c#在gc时回收自己的对象
3. 所有避免gc的操作都是操作内存的, 对应操作byte[]的句柄不要忘记自己回收
剩下你觉得有什么事重要的东西夜整合进去, 然后所有东西都整合在一个mk里 我直接发在csdn上
  • 注意以下所有内容均为chatgpt生成, 不确认是否说的对

C#与Lua之间的引用关系

1. C# 引用 Lua 对象

1.1 引用过程

在C#中引用Lua对象时,通常通过LuaTableLuaFunction等方式进行管理。C#侧会在Lua注册表中增加对应table或function的引用计数,以保证Lua侧不被GC回收。这是通过luaL_ref(L, LUA_REGISTRYINDEX)实现的。

1.2 实现细节

  • 使用 luaL_ref 将 Lua 对象存储在注册表中,并返回一个引用 ID。
  • 通过引用 ID,C# 可以在需要时获取 Lua 对象。
  • 在 C# 侧不再需要该 Lua 对象时,调用 Dispose 方法,释放引用,并减少引用计数。
  • Lua 对象在引用计数为零后,会被 Lua 的 GC 回收。
示例代码
public class MyClass
{
    private LuaFunction _luaFunction;
    private int _luaRef;

    public void SetLuaFunction(LuaFunction luaFunction)
    {
        _luaFunction = luaFunction;
        _luaRef = luaFunction.GetReference();
    }

    public void CallLuaFunction()
    {
        if (_luaRef != 0)
        {
            LuaAPI.lua_getref(luaEnv.L, _luaRef);
            if (LuaAPI.lua_pcall(luaEnv.L, 0, 0, 0) != 0)
            {
                Debug.LogError(LuaAPI.lua_tostring(luaEnv.L, -1));
            }
        }
    }

    ~MyClass()
    {
        if (_luaRef != 0)
        {
            LuaAPI.lua_unref(luaEnv.L, _luaRef);
             GC.SuppressFinalize(this);
        }
    }
}

2. Lua 引用 C# 对象

在Lua中引用C#对象时,C#侧会缓存入栈给Lua的对象,并返回实际索引给Lua。Lua侧使用弱表缓存这些C#对象。

2.1 引用过程

当 Lua 侧需要引用 C# 对象时,C# 侧会将对象缓存,并返回一个索引给 Lua。Lua 使用弱表(设置 __mode = “v”)缓存这个 C# 对象。只要没有其他 Lua 对象引用该 C# 对象,Lua 在 GC 时会触发原表中的 __gc 方法,通知 C# 该对象不再被 Lua 使用。

2.2 实现细节

  • C# 对象入栈并返回索引给 Lua。
  • Lua 在弱表中缓存该 C# 对象。
  • 当 Lua 对象不再引用该 C# 对象时,Lua GC 触发 __gc 方法。
  • C# 在接收到通知后,释放相应的资源,确保对象被 GC 回收。
示例代码
local weakTable = setmetatable({}, {__mode = "v"})
local myGameObject = CS.UnityEngine.GameObject("MyGameObject")
weakTable[1] = myGameObject
public class MyClass
{
    private static Dictionary<int, GameObject> _objectCache = new Dictionary<int, GameObject>();
    private static int _nextId = 1;

    public static int AddObject(GameObject obj)
    {
        int id = _nextId++;
        _objectCache[id] = obj;
        return id;
    }

    public static GameObject GetObject(int id)
    {
        _objectCache.TryGetValue(id, out var obj);
        return obj;
    }

    public static void RemoveObject(int id)
    {
        if (_objectCache.ContainsKey(id))
        {
            _objectCache.Remove(id);
        }
    }
}

3. 内存管理和 GC

3.1 避免 GC 的操作

所有避免 GC 的操作都是操作内存的,因此在进行相应操作时,务必管理好对应的 byte[] 句柄,并确保在不再需要时及时回收。

3.2 示例

确保在 C# 和 Lua 之间传递 byte[] 数据时,适当管理内存,避免内存泄漏。

示例代码
public class MemoryManager
{
    public static IntPtr AllocateByteArray(byte[] data)
    {
        IntPtr ptr = Marshal.AllocHGlobal(data.Length);
        Marshal.Copy(data, 0, ptr, data.Length);
        return ptr;
    }

    public static void FreeByteArray(IntPtr ptr)
    {
        Marshal.FreeHGlobal(ptr);
    }
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值