|
6 | 6 | using System.Linq.Expressions; |
7 | 7 | using System.Reflection; |
8 | 8 | using System.Runtime.CompilerServices; |
| 9 | +using System.Runtime.InteropServices; |
9 | 10 | using System.Runtime.Loader; |
10 | 11 | using System.Text; |
11 | 12 | using System.Threading; |
@@ -199,6 +200,7 @@ public FluentResults.Result Reset() |
199 | 200 | private readonly ConcurrentDictionary<Type, ContentPackage> _pluginPackageLookup = new(); |
200 | 201 | private readonly ConcurrentDictionary<ContentPackage, ImmutableArray<IAssemblyPlugin>> _pluginInstances = new(); |
201 | 202 | private readonly ConditionalWeakTable<IAssemblyLoaderService, ContentPackage> _unloadingAssemblyLoaders = new(); |
| 203 | + private readonly ConcurrentBag<IntPtr> _loadedNativeLibraries = new(); |
202 | 204 | private readonly AsyncReaderWriterLock _operationsLock = new(); |
203 | 205 | private ServiceContainer _pluginInjectorContainer; |
204 | 206 |
|
@@ -632,10 +634,39 @@ private string DoSourceCodeTextCompatibilityPass(string sourceCode) |
632 | 634 | return sourceCode.Replace("GameMain.LuaCs", "LuaCsSetup.Instance"); |
633 | 635 | } |
634 | 636 |
|
635 | | - private IntPtr OnAssemblyLoaderResolvingUnmanaged(Assembly arg1, string arg2) |
| 637 | + private IntPtr OnAssemblyLoaderResolvingUnmanaged(Assembly callerAssembly, string targetAssemblyName) |
636 | 638 | { |
637 | | - // TODO: Implement extern assembly lookup for Native/Unmanaged Assemblies. |
638 | | - throw new NotImplementedException(); |
| 639 | + Guard.IsNull(callerAssembly, nameof(callerAssembly)); |
| 640 | + Guard.IsNullOrWhiteSpace(targetAssemblyName, nameof(targetAssemblyName)); |
| 641 | + |
| 642 | + if (AssemblyLoadContext.GetLoadContext(callerAssembly) is not IAssemblyLoaderService loaderService) |
| 643 | + { |
| 644 | + return IntPtr.Zero; |
| 645 | + } |
| 646 | + |
| 647 | + var targetDirectory = Path.GetFullPath(loaderService.OwnerPackage.Dir); |
| 648 | + if (!targetAssemblyName.TrimEnd().EndsWith(".dll")) |
| 649 | + { |
| 650 | + targetAssemblyName += ".dll"; |
| 651 | + } |
| 652 | + |
| 653 | + var res = _storageService.FindFilesInPackage(loaderService.OwnerPackage, string.Empty, targetAssemblyName, true); |
| 654 | + |
| 655 | + if (res.IsFailed || !res.Value.Any()) |
| 656 | + { |
| 657 | + return IntPtr.Zero; |
| 658 | + } |
| 659 | + |
| 660 | + foreach (var path in res.Value) |
| 661 | + { |
| 662 | + if (System.Runtime.InteropServices.NativeLibrary.TryLoad(path, out IntPtr asmPtr)) |
| 663 | + { |
| 664 | + _loadedNativeLibraries.Add(asmPtr); |
| 665 | + return asmPtr; |
| 666 | + } |
| 667 | + } |
| 668 | + |
| 669 | + return IntPtr.Zero; |
639 | 670 | } |
640 | 671 |
|
641 | 672 | private Assembly OnAssemblyLoaderResolvingManaged(IAssemblyLoaderService requestingLoader, AssemblyName searchName) |
@@ -708,6 +739,25 @@ public FluentResults.Result UnloadManagedAssemblies() |
708 | 739 | _assemblyLoaders.Clear(); |
709 | 740 | GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive, true); |
710 | 741 |
|
| 742 | + // clear native libraries |
| 743 | + if (_loadedNativeLibraries.Any()) |
| 744 | + { |
| 745 | + foreach (var ptr in _loadedNativeLibraries) |
| 746 | + { |
| 747 | + try |
| 748 | + { |
| 749 | + System.Runtime.InteropServices.NativeLibrary.Free(ptr); |
| 750 | + } |
| 751 | + catch |
| 752 | + { |
| 753 | + // ignored |
| 754 | + continue; |
| 755 | + } |
| 756 | + } |
| 757 | + |
| 758 | + _loadedNativeLibraries.Clear(); |
| 759 | + } |
| 760 | + |
711 | 761 | return results; |
712 | 762 | } |
713 | 763 |
|
|
0 commit comments