Skip to content

Commit 5c38319

Browse files
committed
Minor refactoring
1 parent bc9f1fa commit 5c38319

6 files changed

Lines changed: 71 additions & 74 deletions

File tree

scripts/DllManipulator.cs

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Reflection;
55
using System.Reflection.Emit;
66
using System.Runtime.InteropServices;
7-
using System.Runtime.CompilerServices;
87
using System.Threading;
98
using System.IO;
109
using UnityEngine;
@@ -22,7 +21,7 @@ public partial class DllManipulator
2221
public static DllManipulatorOptions Options { get; set; }
2322
private static int _unityMainThreadId;
2423
private static string _assetsPath;
25-
private static LinkedList<object> _antiGcRefHolder = new LinkedList<object>();
24+
private static readonly LinkedList<object> _antiGcRefHolder = new LinkedList<object>();
2625
private static readonly ReaderWriterLockSlim _nativeFunctionLoadLock = new ReaderWriterLockSlim();
2726
private static ModuleBuilder _customDelegateTypesModule = null;
2827
private static readonly Dictionary<string, NativeDll> _dlls = new Dictionary<string, NativeDll>();
@@ -32,10 +31,59 @@ public partial class DllManipulator
3231
private static int _createdDelegateTypes = 0;
3332
private static int _lastNativeCallIndex = 0; //Use with synchronization
3433

35-
internal static void SetUnityContext(int unityMainThreadId, string assetsPath)
34+
/// <summary>
35+
/// Initialization.
36+
/// Finds and mocks relevant native function declarations.
37+
/// If <see cref="DllLoadingMode.Preload"/> option is specified, loads all DLLs specified by these functions.
38+
/// Options have to be configured before calling this method.
39+
/// </summary>
40+
internal static void Initialize(int unityMainThreadId, string assetsPath)
3641
{
37-
DllManipulator._unityMainThreadId = unityMainThreadId;
38-
DllManipulator._assetsPath = assetsPath;
42+
_unityMainThreadId = unityMainThreadId;
43+
_assetsPath = assetsPath;
44+
45+
LowLevelPluginManager.ResetStubPlugin();
46+
47+
Assembly[] assemblies;
48+
if (Options.assemblyPaths.Length == 0)
49+
{
50+
assemblies = new[] { Assembly.GetExecutingAssembly() };
51+
}
52+
else
53+
{
54+
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
55+
assemblies = allAssemblies.Where(a => !a.IsDynamic && Options.assemblyPaths.Any(p => p == PathUtils.NormallizeSystemAssemblyPath(a.Location))).ToArray();
56+
var missingAssemblies = Options.assemblyPaths.Except(assemblies.Select(a => PathUtils.NormallizeSystemAssemblyPath(a.Location)));
57+
foreach (var assemblyPath in missingAssemblies)
58+
{
59+
Debug.LogError($"Could not find assembly at path {assemblyPath}");
60+
}
61+
}
62+
63+
foreach (var assembly in assemblies)
64+
{
65+
var allTypes = assembly.GetTypes();
66+
foreach (var type in allTypes)
67+
{
68+
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
69+
{
70+
if (method.IsDefined(typeof(DllImportAttribute)))
71+
{
72+
if (method.IsDefined(typeof(DisableMockingAttribute)))
73+
continue;
74+
75+
if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute)))
76+
continue;
77+
78+
if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute)))
79+
MockNativeFunction(method);
80+
}
81+
}
82+
}
83+
}
84+
85+
if (Options.loadingMode == DllLoadingMode.Preload)
86+
LoadAll();
3987
}
4088

4189
/// <summary>
@@ -129,36 +177,14 @@ public static IList<NativeDllInfo> GetUsedDllsInfos()
129177
return dllInfos;
130178
}
131179

132-
internal static IEnumerable<MethodInfo> FindNativeFunctionsToMock(Assembly assembly)
133-
{
134-
var allTypes = assembly.GetTypes();
135-
foreach (var type in allTypes)
136-
{
137-
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
138-
{
139-
if (method.IsDefined(typeof(DllImportAttribute)))
140-
{
141-
if (method.IsDefined(typeof(DisableMockingAttribute)))
142-
continue;
143-
144-
if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute)))
145-
continue;
146-
147-
if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute)))
148-
yield return method;
149-
}
150-
}
151-
}
152-
}
153-
154180
private static string ApplyDirectoryPathMacros(string path)
155181
{
156182
return path
157183
.Replace(DLL_PATH_PATTERN_ASSETS_MACRO, _assetsPath)
158184
.Replace(DLL_PATH_PATTERN_PROJECT_MACRO, _assetsPath + "/../");
159185
}
160186

161-
internal static void MockNativeFunction(MethodInfo function)
187+
private static void MockNativeFunction(MethodInfo function)
162188
{
163189
var methodMock = GetNativeFunctionMockMethod(function);
164190
Detour.MarkForNoInlining(function);
@@ -343,7 +369,7 @@ private static Type CreateDelegateTypeForNativeFunctionSignature(NativeFunctionS
343369
var invokeReturnParam = invokeBuilder.DefineParameter(0, functionSignature.returnParameter.parameterAttributes, null);
344370
foreach (var attr in functionSignature.returnParameter.customAttributes)
345371
{
346-
var attrBuilder = CreateMarshalingAttributeBuilderFromAttributeInstance(attr, functionName);
372+
var attrBuilder = CreateAttributeBuilderFromAttributeInstance(attr, functionName);
347373
if(attrBuilder != null)
348374
invokeReturnParam.SetCustomAttribute(attrBuilder);
349375
}
@@ -353,7 +379,7 @@ private static Type CreateDelegateTypeForNativeFunctionSignature(NativeFunctionS
353379
var paramBuilder = invokeBuilder.DefineParameter(i + 1, param.parameterAttributes, null);
354380
foreach(var attr in param.customAttributes)
355381
{
356-
var attrBuilder = CreateMarshalingAttributeBuilderFromAttributeInstance(attr, functionName);
382+
var attrBuilder = CreateAttributeBuilderFromAttributeInstance(attr, functionName);
357383
if (attrBuilder != null)
358384
paramBuilder.SetCustomAttribute(attrBuilder);
359385
}
@@ -363,15 +389,15 @@ private static Type CreateDelegateTypeForNativeFunctionSignature(NativeFunctionS
363389
return delBuilder.CreateType();
364390
}
365391

366-
private static CustomAttributeBuilder CreateMarshalingAttributeBuilderFromAttributeInstance(Attribute attribute, string nativeFunctionName)
392+
private static CustomAttributeBuilder CreateAttributeBuilderFromAttributeInstance(Attribute attribute, string nativeFunctionName)
367393
{
368394
var attrType = attribute.GetType();
369395
switch (attribute)
370396
{
371397
case MarshalAsAttribute marshalAsAttribute:
372398
{
373399
if(marshalAsAttribute.Value == UnmanagedType.LPArray) // Used to bypass Mono bug, see https://github.com/mono/mono/issues/16570
374-
throw new Exception("UnmanagedType.LPArray in [MarshalAs] attribute is not supported. See Limitations section");
400+
throw new Exception("UnmanagedType.LPArray in [MarshalAs] attribute is not supported. See Limitations section.");
375401

376402
object[] ctorArgs = { marshalAsAttribute.Value };
377403

@@ -392,7 +418,7 @@ private static CustomAttributeBuilder CreateMarshalingAttributeBuilderFromAttrib
392418
}
393419
default:
394420
{
395-
Debug.LogWarning($"Skipping attribute [{attrType.Name}] in function {nativeFunctionName} as it is not supported. However, adding the support should be ease.");
421+
Debug.LogWarning($"Skipping copy of attribute [{attrType.Name}] in function {nativeFunctionName} as it is not supported. However, if it is desirable to include it, adding such support should be easy. See the method that throws this exception.");
396422
return null;
397423
}
398424
}
@@ -538,9 +564,9 @@ private static IntPtr SysLoadDll(string filepath)
538564
#if UNITY_STANDALONE_WIN
539565
return PInvokes_Windows.LoadLibrary(filepath);
540566
#elif UNITY_STANDALONE_LINUX
541-
return PInvokes_Linux.dlopen(filepath, (int)Options.unixDlopenFlags);
567+
return PInvokes_Linux.dlopen(filepath, (int)Options.posixDlopenFlags);
542568
#elif UNITY_STANDALONE_OSX
543-
return PInvokes_Osx.dlopen(filepath, (int)Options.unixDlopenFlags);
569+
return PInvokes_Osx.dlopen(filepath, (int)Options.posixDlopenFlags);
544570
#endif
545571
}
546572

@@ -573,7 +599,7 @@ public class DllManipulatorOptions
573599
public string dllPathPattern;
574600
public string[] assemblyPaths; //empty means only executing assembly
575601
public DllLoadingMode loadingMode;
576-
public Unix_DlopenFlags unixDlopenFlags;
602+
public PosixDlopenFlags posixDlopenFlags;
577603
public bool threadSafe;
578604
public bool enableCrashLogs;
579605
public string crashLogsDir;

scripts/DllManipulatorScript.cs

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class DllManipulatorScript : MonoBehaviour
2323
#endif
2424
assemblyPaths = new string[0],
2525
loadingMode = DllLoadingMode.Lazy,
26-
unixDlopenFlags = Unix_DlopenFlags.Lazy,
26+
posixDlopenFlags = PosixDlopenFlags.Lazy,
2727
threadSafe = false,
2828
enableCrashLogs = false,
2929
crashLogsDir = "{assets}/",
@@ -47,42 +47,13 @@ private void OnEnable()
4747
_singletonInstance = this;
4848
DontDestroyOnLoad(gameObject);
4949

50-
var timer = System.Diagnostics.Stopwatch.StartNew();
50+
var initTimer = System.Diagnostics.Stopwatch.StartNew();
5151

52-
LowLevelPluginManager.ResetStubPlugin();
53-
54-
DllManipulator.SetUnityContext(Thread.CurrentThread.ManagedThreadId, Application.dataPath);
5552
DllManipulator.Options = Options;
53+
DllManipulator.Initialize(Thread.CurrentThread.ManagedThreadId, Application.dataPath);
5654

57-
Assembly[] assemblies;
58-
if (Options.assemblyPaths.Length == 0)
59-
{
60-
assemblies = new[] { Assembly.GetExecutingAssembly() };
61-
}
62-
else
63-
{
64-
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
65-
assemblies = allAssemblies.Where(a => !a.IsDynamic && Options.assemblyPaths.Any(p => p == PathUtils.NormallizeSystemAssemblyPath(a.Location))).ToArray();
66-
var missingAssemblies = Options.assemblyPaths.Except(assemblies.Select(a => PathUtils.NormallizeSystemAssemblyPath(a.Location)));
67-
foreach(var assemblyPath in missingAssemblies)
68-
{
69-
Debug.LogError($"Could not find assembly at path {assemblyPath}");
70-
}
71-
}
72-
73-
foreach (var assembly in assemblies)
74-
{
75-
foreach (var function in DllManipulator.FindNativeFunctionsToMock(assembly))
76-
{
77-
DllManipulator.MockNativeFunction(function);
78-
}
79-
}
80-
81-
if (DllManipulator.Options.loadingMode == DllLoadingMode.Preload)
82-
DllManipulator.LoadAll();
83-
84-
timer.Stop();
85-
InitializationTime = timer.Elapsed;
55+
initTimer.Stop();
56+
InitializationTime = initTimer.Elapsed;
8657
}
8758

8859
private void OnDestroy()

scripts/Editor/DllManipulatorEditor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class DllManipulatorEditor : Editor
3232
"Specifies how DLLs and functions will be loaded.\n\n" +
3333
"Lazy - All DLLs and functions are loaded each time they are called, if not loaded yet. This allows them to be easily unloaded and loaded within game execution.\n\n" +
3434
"Preloaded - Slight performance benefit over Lazy mode. All declared DLLs and functions are loaded at startup (OnEnable()) and not reloaded later. Mid-execution it's not safe to unload them unless game is paused.");
35-
private static readonly GUIContent UNIX_DLOPEN_FLAGS_GUI_CONTENT = new GUIContent("dlopen flags",
35+
private static readonly GUIContent POSIX_DLOPEN_FLAGS_GUI_CONTENT = new GUIContent("dlopen flags",
3636
"Flags used in dlopen() P/Invoke on Linux and OSX systems. Has minor meaning unless library is large.");
3737
private static readonly GUIContent THREAD_SAFE_GUI_CONTENT = new GUIContent("Thread safe",
3838
"Ensures synchronization required for native calls from any other than Unity main thread. Overhead might be few times higher, with uncontended locks.\n\n" +
@@ -252,7 +252,7 @@ private void DrawOptions(DllManipulatorOptions options)
252252
options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode);
253253

254254
#if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX
255-
options.unixDlopenFlags = (Unix_DlopenFlags)EditorGUILayout.EnumPopup(UNIX_DLOPEN_FLAGS_GUI_CONTENT, options.unixDlopenFlags);
255+
options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags);
256256
#endif
257257

258258
guiEnabledStack.Push(GUI.enabled);

scripts/LowLevelPluginManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static void OnDllLoaded(NativeDll dll)
4040
}
4141
catch (DllNotFoundException)
4242
{
43-
Debug.LogWarning("StubLluiPlugin not found. UnityPluginLoad and UnityPluginUnload callbacks won't fire. If you didn't install UnityNativeTool from .unitypackage or it didn't contain the compiled plugin, you'll need to compile it manually. Alternatively, you may comment out this warning if you don't care about these callbacks.");
43+
Debug.LogWarning("StubLluiPlugin not found. UnityPluginLoad and UnityPluginUnload callbacks won't fire. If you didn't install UnityNativeTool from .unitypackage or it didn't contain the compiled plugin, you'll need to compile it manually. You may also comment out this warning if you don't care about these callbacks.");
4444
}
4545
finally
4646
{

scripts/PInvokes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ internal static class PInvokes_Osx
111111
public static extern int dlclose(IntPtr handle);
112112
}
113113

114-
public enum Unix_DlopenFlags : int
114+
public enum PosixDlopenFlags : int
115115
{
116116
Lazy = 0x00001,
117117
Now = 0x00002,

0 commit comments

Comments
 (0)