11using System ;
2+ using System . Collections . Generic ;
23using System . Runtime . InteropServices ;
34using ZenKit . Daedalus ;
5+ using ZenKit . Util ;
46
57namespace 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}
0 commit comments