use UserData instead of tables

This commit is contained in:
Alessandro Proto 2023-02-12 09:49:51 +01:00
parent 7254ba638c
commit d318523bde

View file

@ -14,11 +14,12 @@ namespace Capy64.Runtime;
public class ObjectManager : IPlugin public class ObjectManager : IPlugin
{ {
private static ConcurrentDictionary<nint, object> _objects = new(); private static ConcurrentDictionary<nint, object> _objects = new();
private static IGame _game; private static IGame _game;
public ObjectManager(IGame game) public ObjectManager(IGame game)
{ {
_game = game; _game = game;
_game.EventEmitter.OnClose += OnClone; _game.EventEmitter.OnClose += OnClose;
} }
public static void PushObject<T>(Lua L, T obj) public static void PushObject<T>(Lua L, T obj)
@ -29,93 +30,51 @@ public class ObjectManager : IPlugin
return; return;
} }
L.NewTable(); var p = L.NewUserData(1);
var rp = L.ToPointer(-1); _objects[p] = obj;
//var handle = GCHandle.Alloc(obj);
//var op = GCHandle.ToIntPtr(handle);
_objects[rp] = obj;
} }
public static T ToObject<T>(Lua L, int index, bool freeGCHandle = true) public static T ToObject<T>(Lua L, int index, bool freeGCHandle = true)
{ {
if (L.IsNil(index) || !L.IsTable(index)) if (L.IsNil(index) || !L.IsUserData(index))
return default(T); return default(T);
var rp = L.ToPointer(index); var data = L.ToUserData(index);
if (rp == IntPtr.Zero) if (data == IntPtr.Zero)
return default(T); return default(T);
if (!_objects.ContainsKey(rp)) if (!_objects.ContainsKey(data))
return default(T); return default(T);
var obj = _objects[rp]; var reference = (T)_objects[data];
if(obj == null)
return default(T);
if (freeGCHandle) if (freeGCHandle)
_objects.Remove(rp, out _); _objects.Remove(data, out _);
return (T)obj; return reference;
/*var handle = GCHandle.FromIntPtr(Objects[rp]);
if (!handle.IsAllocated)
return default(T);
var reference = (T)handle.Target;
if (freeGCHandle)
handle.Free();
return reference;*/
} }
public static T CheckObject<T>(Lua L, int argument, string typeName, bool freeGCHandle = true) public static T CheckObject<T>(Lua L, int argument, string typeName, bool freeGCHandle = true)
{ {
if (L.IsNil(argument) || !L.IsTable(argument)) if (L.IsNil(argument) || !L.IsUserData(argument))
return default(T); return default(T);
if(L.GetMetaField(argument, "__name") != LuaType.String) IntPtr data = L.CheckUserData(argument, typeName);
if (data == IntPtr.Zero)
return default(T); return default(T);
var mtName = L.ToString(-1); if (!_objects.ContainsKey(data))
L.Pop(1);
if(mtName != typeName)
return default(T); return default(T);
var rp = L.ToPointer(argument); var reference = (T)_objects[data];
if (rp == IntPtr.Zero)
return default(T);
if (!_objects.ContainsKey(rp))
return default(T);
var obj = _objects[rp];
if (obj == null)
return default(T);
if (freeGCHandle) if (freeGCHandle)
_objects.Remove(rp, out _); _objects.Remove(data, out _);
return (T)obj; return reference;
/*
var handle = GCHandle.FromIntPtr(Objects[rp]);
if (!handle.IsAllocated)
return default(T);
var reference = (T)handle.Target;
if (freeGCHandle)
handle.Free();
return reference;*/
} }
private void OnClone(object sender, EventArgs e) private void OnClose(object sender, EventArgs e)
{ {
_objects.Clear(); _objects.Clear();
} }