Skip to content

Commit b67596a

Browse files
committed
feat(DaedalusVm): implement transient instances
To use them, implement the `IDaedalusTransientInstance` interface, create an instance of your implementation and call `DaedalusInstance.CreateTransient` with it. The result will be a `DaedalusInstance` of type `Invalid`.
1 parent a43c381 commit b67596a

2 files changed

Lines changed: 148 additions & 2 deletions

File tree

ZenKit/DaedalusInstance.cs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Runtime.InteropServices;
34
using ZenKit.Daedalus;
5+
using ZenKit.Util;
46

57
namespace ZenKit
68
{
@@ -93,5 +95,121 @@ public object? UserData
9395
_ => new DaedalusInstance(handle)
9496
};
9597
}
98+
99+
public static DaedalusInstance CreateTransient(IDaedalusTransientInstance impl)
100+
{
101+
return new DaedalusInstance(IDaedalusTransientInstance.Create(impl));
102+
}
103+
}
104+
105+
public interface IDaedalusTransientInstance
106+
{
107+
private static readonly List<GCHandle> KeepaliveList = new List<GCHandle>();
108+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceIntGetter NativeIntGetterCallback =
109+
_nativeIntGetterCallbackHandler;
110+
111+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceIntSetter NativeIntSetterCallback =
112+
_nativeIntSetterCallbackHandler;
113+
114+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceFloatGetter NativeFloatGetterCallback =
115+
_nativeFloatGetterCallbackHandler;
116+
117+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceFloatSetter NativeFloatSetterCallback =
118+
_nativeFloatSetterCallbackHandler;
119+
120+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceStringGetter NativeStringGetterCallback =
121+
_nativeStringGetterCallbackHandler;
122+
123+
private static readonly Native.Callbacks.ZkDaedalusTransientInstanceStringSetter NativeStringSetterCallback =
124+
_nativeStringSetterCallbackHandler;
125+
126+
internal static UIntPtr Create(IDaedalusTransientInstance impl)
127+
{
128+
129+
var ptr = GCHandle.Alloc(impl);
130+
KeepaliveList.Add(ptr);
131+
return Native.ZkDaedalusInstance_newTransient(
132+
GCHandle.ToIntPtr(ptr),
133+
NativeIntGetterCallback,
134+
NativeIntSetterCallback,
135+
NativeFloatGetterCallback,
136+
NativeFloatSetterCallback,
137+
NativeStringGetterCallback,
138+
NativeStringSetterCallback
139+
);
140+
}
141+
142+
public static void ReleaseAll()
143+
{
144+
KeepaliveList.ForEach(handle => handle.Free());
145+
KeepaliveList.Clear();
146+
}
147+
148+
public void SetInt(DaedalusSymbol sym, ushort idx, int val);
149+
public void SetFloat(DaedalusSymbol sym, ushort idx, float val);
150+
public void SetString(DaedalusSymbol sym, ushort idx, string val);
151+
152+
public int GetInt(DaedalusSymbol sym, ushort idx);
153+
public float GetFloat(DaedalusSymbol sym, ushort idx);
154+
public string GetString(DaedalusSymbol sym, ushort idx);
155+
156+
[MonoPInvokeCallback]
157+
private static int _nativeIntGetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx)
158+
{
159+
var gcHandle = GCHandle.FromIntPtr(ctx);
160+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
161+
return impl.GetInt(new DaedalusSymbol(sym), idx);
162+
}
163+
164+
[MonoPInvokeCallback]
165+
private static void _nativeIntSetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx, int val)
166+
{
167+
var gcHandle = GCHandle.FromIntPtr(ctx);
168+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
169+
impl.SetInt(new DaedalusSymbol(sym), idx, val);
170+
}
171+
172+
[MonoPInvokeCallback]
173+
private static float _nativeFloatGetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx)
174+
{
175+
var gcHandle = GCHandle.FromIntPtr(ctx);
176+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
177+
return impl.GetFloat(new DaedalusSymbol(sym), idx);
178+
}
179+
180+
[MonoPInvokeCallback]
181+
private static void _nativeFloatSetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx, float val)
182+
{
183+
var gcHandle = GCHandle.FromIntPtr(ctx);
184+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
185+
impl.SetFloat(new DaedalusSymbol(sym), idx, val);
186+
}
187+
188+
private static IntPtr _stringCache = IntPtr.Zero;
189+
190+
[MonoPInvokeCallback]
191+
private static IntPtr _nativeStringGetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx)
192+
{
193+
var gcHandle = GCHandle.FromIntPtr(ctx);
194+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
195+
196+
// Need to avoid memory leaks
197+
if (_stringCache != IntPtr.Zero)
198+
{
199+
Marshal.FreeHGlobal(_stringCache);
200+
_stringCache = IntPtr.Zero;
201+
}
202+
203+
_stringCache = GothicStringMarshaller.Instance.MarshalManagedToNative(impl.GetString(new DaedalusSymbol(sym), idx));
204+
return _stringCache;
205+
}
206+
207+
[MonoPInvokeCallback]
208+
private static void _nativeStringSetterCallbackHandler(IntPtr ctx, UIntPtr sym, ushort idx, string val)
209+
{
210+
var gcHandle = GCHandle.FromIntPtr(ctx);
211+
var impl = (IDaedalusTransientInstance)gcHandle.Target;
212+
impl.SetString(new DaedalusSymbol(sym), idx, val);
213+
}
96214
}
97215
}

ZenKit/Native.cs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ internal static byte[] Encode(string s)
4848

4949
internal class GothicStringMarshaller : ICustomMarshaler
5050
{
51-
private static GothicStringMarshaller _instance = new GothicStringMarshaller();
51+
public static readonly GothicStringMarshaller Instance = new GothicStringMarshaller();
5252

5353
public static ICustomMarshaler GetInstance(string cookie)
5454
{
55-
return _instance;
55+
return Instance;
5656
}
5757

5858
public void CleanUpManagedData(object ManagedObj)
@@ -4223,6 +4223,16 @@ public static extern void ZkDaedalusScript_enumerateInstanceSymbols(UIntPtr slf,
42234223
[DllImport(DllName)]
42244224
public static extern void ZkDaedalusInstance_release(UIntPtr slf);
42254225

4226+
[DllImport(DllName)]
4227+
public static extern UIntPtr ZkDaedalusInstance_newTransient(IntPtr ctx,
4228+
ZkDaedalusTransientInstanceIntGetter getInt,
4229+
ZkDaedalusTransientInstanceIntSetter setInt,
4230+
ZkDaedalusTransientInstanceFloatGetter getFloat,
4231+
ZkDaedalusTransientInstanceFloatSetter setFloat,
4232+
ZkDaedalusTransientInstanceStringGetter getString,
4233+
ZkDaedalusTransientInstanceStringSetter setString
4234+
);
4235+
42264236
[DllImport(DllName)]
42274237
public static extern DaedalusDataType ZkDaedalusSymbol_getReturnType(UIntPtr slf);
42284238

@@ -7933,6 +7943,24 @@ public class Callbacks
79337943

79347944
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
79357945
public delegate bool ZkVirtualObjectEnumerator(UIntPtr ctx, UIntPtr vob);
7946+
7947+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7948+
public delegate int ZkDaedalusTransientInstanceIntGetter(IntPtr ctx, UIntPtr sym, ushort idx);
7949+
7950+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7951+
public delegate void ZkDaedalusTransientInstanceIntSetter(IntPtr ctx, UIntPtr sym, ushort idx, int val);
7952+
7953+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7954+
public delegate float ZkDaedalusTransientInstanceFloatGetter(IntPtr ctx, UIntPtr sym, ushort idx);
7955+
7956+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7957+
public delegate void ZkDaedalusTransientInstanceFloatSetter(IntPtr ctx, UIntPtr sym, ushort idx, float val);
7958+
7959+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7960+
public delegate IntPtr ZkDaedalusTransientInstanceStringGetter(IntPtr ctx, UIntPtr sym, ushort idx);
7961+
7962+
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
7963+
public delegate void ZkDaedalusTransientInstanceStringSetter(IntPtr ctx, UIntPtr sym, ushort idx, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(GothicStringMarshaller))] string val);
79367964
}
79377965

79387966
public class Structs

0 commit comments

Comments
 (0)