@@ -30,6 +30,9 @@ public partial class DllManipulator
3030 private static List < NativeFunction > _mockedNativeFunctions = new List < NativeFunction > ( ) ;
3131 private static int _createdDelegateTypes = 0 ;
3232 private static int _lastNativeCallIndex = 0 ; //Use with synchronization
33+ private static List < MethodInfo > _customLoadedTriggers = null ;
34+ private static List < MethodInfo > _customBeforeUnloadTriggers = null ;
35+ private static List < MethodInfo > _customAfterUnloadTriggers = null ;
3336
3437 /// <summary>
3538 /// Initialization.
@@ -78,6 +81,18 @@ internal static void Initialize(int unityMainThreadId, string assetsPath)
7881 if ( Options . mockAllNativeFunctions || method . IsDefined ( typeof ( MockNativeDeclarationAttribute ) ) || method . DeclaringType . IsDefined ( typeof ( MockNativeDeclarationsAttribute ) ) )
7982 MockNativeFunction ( method ) ;
8083 }
84+ else if ( method . IsDefined ( typeof ( NativeDllLoadedTriggerAttribute ) ) )
85+ {
86+ RegisterTriggerMethod ( method , ref _customLoadedTriggers ) ;
87+ }
88+ else if ( method . IsDefined ( typeof ( NativeDllBeforeUnloadTriggerAttribute ) ) )
89+ {
90+ RegisterTriggerMethod ( method , ref _customBeforeUnloadTriggers ) ;
91+ }
92+ else if ( method . IsDefined ( typeof ( NativeDllAfterUnloadTriggerAttribute ) ) )
93+ {
94+ RegisterTriggerMethod ( method , ref _customAfterUnloadTriggers ) ;
95+ }
8196 }
8297 }
8398 }
@@ -86,6 +101,21 @@ internal static void Initialize(int unityMainThreadId, string assetsPath)
86101 LoadAll ( ) ;
87102 }
88103
104+ private static void RegisterTriggerMethod ( MethodInfo method , ref List < MethodInfo > triggersList )
105+ {
106+ var parameters = method . GetParameters ( ) ;
107+ if ( parameters . Length == 0 || parameters . Length == 1 && parameters [ 0 ] . ParameterType == typeof ( NativeDll ) )
108+ {
109+ if ( triggersList == null )
110+ triggersList = new List < MethodInfo > ( 2 ) ;
111+ triggersList . Add ( method ) ;
112+ }
113+ else
114+ {
115+ Debug . LogError ( $ "Trigger method must either take no parameters or one parameter of type { nameof ( NativeDll ) } . Violation on method { method . Name } in { method . DeclaringType . FullName } ") ;
116+ }
117+ }
118+
89119 /// <summary>
90120 /// Loads all DLLs and functions for mocked methods
91121 /// </summary>
@@ -124,12 +154,14 @@ public static void UnloadAll()
124154 if ( dll . handle != IntPtr . Zero )
125155 {
126156 LowLevelPluginManager . OnBeforeDllUnload ( dll ) ;
157+ InvokeCustomTriggers ( _customBeforeUnloadTriggers , dll ) ;
127158
128159 bool success = SysUnloadDll ( dll . handle ) ;
129160 if ( ! success )
130161 Debug . LogWarning ( $ "Error while unloading DLL \" { dll . name } \" at path \" { dll . path } \" ") ;
131162
132163 dll . ResetAsUnloaded ( ) ;
164+ InvokeCustomTriggers ( _customAfterUnloadTriggers , dll ) ;
133165 }
134166 }
135167 }
@@ -449,6 +481,7 @@ internal static void LoadTargetFunction(NativeFunction nativeFunction, bool igno
449481 else
450482 {
451483 dll . loadingError = false ;
484+ InvokeCustomTriggers ( _customLoadedTriggers , dll ) ;
452485 LowLevelPluginManager . OnDllLoaded ( dll ) ;
453486 }
454487 }
@@ -476,6 +509,20 @@ internal static void LoadTargetFunction(NativeFunction nativeFunction, bool igno
476509 }
477510 }
478511
512+ private static void InvokeCustomTriggers ( List < MethodInfo > triggers , NativeDll dll )
513+ {
514+ if ( triggers == null )
515+ return ;
516+
517+ foreach ( var triggerMethod in triggers )
518+ {
519+ if ( triggerMethod . GetParameters ( ) . Length == 1 )
520+ triggerMethod . Invoke ( null , new object [ ] { dll } ) ;
521+ else
522+ triggerMethod . Invoke ( null , Array . Empty < object > ( ) ) ;
523+ }
524+ }
525+
479526 /// <summary>
480527 /// Logs native function's call to file. If that file exists, it is overwritten. One file is maintained for each thread.
481528 /// Note: This method is being called by dynamically generated code. Be careful when changing its signature.
0 commit comments