Hacky object management

This commit is contained in:
Alessandro Proto 2023-02-11 22:59:57 +01:00
parent b84db27f83
commit 7254ba638c
6 changed files with 140 additions and 10 deletions

View file

@ -542,7 +542,9 @@ public class FileSystem : IPlugin
} }
var fileStream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite); var fileStream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite);
L.PushObject(fileStream);
ObjectManager.PushObject(L, fileStream);
//L.PushObject(fileStream);
L.SetMetaTable(FileHandle.ObjectType); L.SetMetaTable(FileHandle.ObjectType);
return 1; return 1;

View file

@ -397,7 +397,8 @@ public class GPU : IPlugin
var buffer = new uint[_game.Width * _game.Height]; var buffer = new uint[_game.Width * _game.Height];
_game.Drawing.Canvas.GetData(buffer); _game.Drawing.Canvas.GetData(buffer);
L.PushObject(buffer); ObjectManager.PushObject(L, buffer);
//L.PushObject(buffer);
L.SetMetaTable(GPUBuffer.ObjectType); L.SetMetaTable(GPUBuffer.ObjectType);
return 1; return 1;
@ -423,7 +424,7 @@ public class GPU : IPlugin
var buffer = new uint[width * height]; var buffer = new uint[width * height];
L.PushObject(buffer); ObjectManager.PushObject(L, buffer);
L.SetMetaTable(GPUBuffer.ObjectType); L.SetMetaTable(GPUBuffer.ObjectType);
return 1; return 1;
@ -484,7 +485,7 @@ public class GPU : IPlugin
var data = new uint[texture.Width * texture.Height]; var data = new uint[texture.Width * texture.Height];
texture.GetData(data); texture.GetData(data);
L.PushObject(data); ObjectManager.PushObject(L, data);
L.SetMetaTable(GPUBuffer.ObjectType); L.SetMetaTable(GPUBuffer.ObjectType);
L.PushInteger(texture.Width); L.PushInteger(texture.Width);
L.PushInteger(texture.Height); L.PushInteger(texture.Height);

View file

@ -210,7 +210,8 @@ public class HTTP : IPlugin
LK.PushInteger(requestId); LK.PushInteger(requestId);
// arg 2, response data // arg 2, response data
L.PushObject(stream); ObjectManager.PushObject(L, stream);
//L.PushObject(stream);
L.SetMetaTable(FileHandle.ObjectType); L.SetMetaTable(FileHandle.ObjectType);
/*if ((bool)options["binary"]) /*if ((bool)options["binary"])
BinaryReadHandle.Push(LK, new(stream)); BinaryReadHandle.Push(LK, new(stream));

View file

@ -0,0 +1,122 @@
using Capy64.API;
using KeraLua;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Capy64.Runtime;
public class ObjectManager : IPlugin
{
private static ConcurrentDictionary<nint, object> _objects = new();
private static IGame _game;
public ObjectManager(IGame game)
{
_game = game;
_game.EventEmitter.OnClose += OnClone;
}
public static void PushObject<T>(Lua L, T obj)
{
if (obj == null)
{
L.PushNil();
return;
}
L.NewTable();
var rp = L.ToPointer(-1);
//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)
{
if (L.IsNil(index) || !L.IsTable(index))
return default(T);
var rp = L.ToPointer(index);
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)
_objects.Remove(rp, out _);
return (T)obj;
/*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)
{
if (L.IsNil(argument) || !L.IsTable(argument))
return default(T);
if(L.GetMetaField(argument, "__name") != LuaType.String)
return default(T);
var mtName = L.ToString(-1);
L.Pop(1);
if(mtName != typeName)
return default(T);
var rp = L.ToPointer(argument);
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)
_objects.Remove(rp, out _);
return (T)obj;
/*
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)
{
_objects.Clear();
}
}

View file

@ -97,12 +97,14 @@ public class FileHandle : IPlugin
private static Stream ToStream(Lua L, bool gc = false) private static Stream ToStream(Lua L, bool gc = false)
{ {
return L.CheckObject<Stream>(1, ObjectType, gc); return ObjectManager.ToObject<Stream>(L, 1, gc);
//return L.CheckObject<Stream>(1, ObjectType, gc);
} }
private static Stream CheckStream(Lua L, bool gc = false) private static Stream CheckStream(Lua L, bool gc = false)
{ {
var obj = L.CheckObject<Stream>(1, ObjectType, gc); var obj = ObjectManager.CheckObject<Stream>(L, 1, ObjectType, gc);
//var obj = L.CheckObject<Stream>(1, ObjectType, gc);
if (obj is null) if (obj is null)
{ {
L.Error("attempt to use a closed file"); L.Error("attempt to use a closed file");

View file

@ -58,18 +58,20 @@ public class GPUBuffer : IPlugin
public static uint[] ToBuffer(Lua L, bool gc = false) public static uint[] ToBuffer(Lua L, bool gc = false)
{ {
return L.CheckObject<uint[]>(1, ObjectType, gc); return ObjectManager.ToObject<uint[]>(L, 1, gc);
//return L.CheckObject<uint[]>(1, ObjectType, gc);
} }
public static uint[] CheckBuffer(Lua L, bool gc = false) public static uint[] CheckBuffer(Lua L, bool gc = false)
{ {
var obj = L.CheckObject<uint[]>(1, ObjectType, gc); var obj = ObjectManager.CheckObject<uint[]>(L, 1, ObjectType, gc);
//var obj = L.CheckObject<uint[]>(1, ObjectType, gc);
if (obj is null) if (obj is null)
{ {
L.Error("attempt to use a closed buffer"); L.Error("attempt to use a closed buffer");
return null; return null;
} }
return (uint[])obj; return obj;
} }
private static int LM_Index(IntPtr state) private static int LM_Index(IntPtr state)