33using System . IO ;
44using System . Reflection ;
55using System . Runtime . InteropServices ;
6+ using System . Threading ;
67
78namespace AltV . Net . Host
89{
910 public class Host
1011 {
11- private static IDictionary < string , ResourceAssemblyLoadContext > _loadContexts =
12+ private static readonly IDictionary < string , ResourceAssemblyLoadContext > _loadContexts =
1213 new Dictionary < string , ResourceAssemblyLoadContext > ( ) ;
1314
15+ private const string DllName = "csharp-module" ;
16+ private const CallingConvention NativeCallingConvention = CallingConvention . Cdecl ;
17+
18+ internal delegate int CoreClrDelegate ( IntPtr args , int argsLength ) ;
19+
20+ [ DllImport ( DllName , CallingConvention = NativeCallingConvention ) ]
21+ internal static extern void CoreClr_SetResourceLoadDelegates ( CoreClrDelegate resourceExecute ,
22+ CoreClrDelegate resourceExecuteUnload ) ;
23+
24+ private static CoreClrDelegate _executeResource ;
25+
26+ private static CoreClrDelegate _executeResourceUnload ;
27+
1428 /// <summary>
1529 /// Main is present to execute the dll as a assembly
1630 /// </summary>
17- static void Main ( )
31+ static int Main ( string [ ] args )
1832 {
19- //TODO: init stuff we need
20- Console . WriteLine ( "Init host" ) ;
33+ var semaphore = new Semaphore ( 0 , 1 ) ;
34+ SetDelegates ( ) ;
35+ semaphore . WaitOne ( ) ;
36+ return 0 ;
37+ }
38+
39+ public static int Main2 ( IntPtr arg , int argLength )
40+ {
41+ SetDelegates ( ) ;
42+ return 0 ;
43+ }
44+
45+ private static void SetDelegates ( )
46+ {
47+ _executeResource = ExecuteResource ;
48+ GCHandle . Alloc ( _executeResource ) ;
49+ _executeResourceUnload = ExecuteResourceUnload ;
50+ GCHandle . Alloc ( _executeResourceUnload ) ;
51+ CoreClr_SetResourceLoadDelegates ( _executeResource , _executeResourceUnload ) ;
2152 }
2253
2354 private static string GetPath ( string resourcePath , string resourceMain ) =>
24- $ "{ resourcePath } / { resourceMain } ";
55+ $ "{ resourcePath } { Path . DirectorySeparatorChar } { resourceMain } ";
2556
2657 [ StructLayout ( LayoutKind . Sequential ) ]
2758 public struct LibArgs
@@ -56,6 +87,8 @@ public static int ExecuteResource(IntPtr arg, int argLength)
5687 var resourceAssemblyLoadContext =
5788 new ResourceAssemblyLoadContext ( resourceDllPath , resourcePath , resourceName ) ;
5889
90+ _loadContexts [ resourceDllPath ] = resourceAssemblyLoadContext ;
91+
5992 Assembly resourceAssembly ;
6093
6194 try
@@ -65,21 +98,18 @@ public static int ExecuteResource(IntPtr arg, int argLength)
6598 catch ( FileLoadException e )
6699 {
67100 Console . WriteLine ( $ "Threw a exception while loading the assembly \" { resourceDllPath } \" : { e } ") ;
68- resourceAssembly = null ;
101+ return 1 ;
69102 }
70103
71104 var altVNetAssembly = resourceAssemblyLoadContext . LoadFromAssemblyName ( new AssemblyName ( "AltV.Net" ) ) ;
72105 foreach ( var type in altVNetAssembly . GetTypes ( ) )
73106 {
74- if ( type . Name == "ModuleWrapper" )
75- {
76- type . GetMethod ( "MainWithAssembly" , BindingFlags . Public | BindingFlags . Static ) ? . Invoke ( null ,
77- new object [ ] { libArgs . ServerPointer , libArgs . ResourcePointer , resourceAssemblyLoadContext } ) ;
78- }
107+ if ( type . Name != "ModuleWrapper" ) continue ;
108+ type . GetMethod ( "MainWithAssembly" , BindingFlags . Public | BindingFlags . Static ) ? . Invoke ( null ,
109+ new object [ ] { libArgs . ServerPointer , libArgs . ResourcePointer , resourceAssemblyLoadContext } ) ;
110+ break ;
79111 }
80112
81- _loadContexts [ resourceDllPath ] = resourceAssemblyLoadContext ;
82-
83113 return 0 ;
84114 }
85115
@@ -97,7 +127,14 @@ public static int ExecuteResourceUnload(IntPtr arg, int argLength)
97127 var resourceDllPath = GetPath ( resourcePath , resourceMain ) ;
98128
99129 if ( ! _loadContexts . Remove ( resourceDllPath , out var loadContext ) ) return 1 ;
130+ var loadContextWeakReference = new WeakReference ( loadContext ) ;
100131 loadContext . Unload ( ) ;
132+ for ( var i = 0 ; loadContextWeakReference . IsAlive && ( i < 10 ) ; i ++ )
133+ {
134+ GC . Collect ( ) ;
135+ GC . WaitForPendingFinalizers ( ) ;
136+ }
137+
101138 return 0 ;
102139 }
103140 }
0 commit comments