Skip to content

Commit 8f54d67

Browse files
MichalStrehovskyjkotas
authored andcommitted
Move NativeLibrary to the shared partition (dotnet#24143)
I'm taking the LibraryNameVariation helper from System.Runtime.Loader for the ride as well because it's a general purpose probing logic that is useful in a managed implementation of NativeLibrary.
1 parent 11ec759 commit 8f54d67

File tree

8 files changed

+172
-112
lines changed

8 files changed

+172
-112
lines changed

src/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@
242242
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Expando\IExpando.cs" />
243243
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\GCHandle.CoreCLR.cs" />
244244
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.CoreCLR.cs" />
245-
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.cs" />
245+
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.CoreCLR.cs" />
246246
<Compile Include="$(BclSourcesRoot)\System\Runtime\Loader\AssemblyDependencyResolver.cs" />
247247
<Compile Include="$(BclSourcesRoot)\System\Runtime\Loader\AssemblyLoadContext.CoreCLR.cs" />
248248
<Compile Include="$(BclSourcesRoot)\System\Runtime\Versioning\CompatibilitySwitch.cs" />

src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,7 @@
673673
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MemoryMarshal.cs" />
674674
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MemoryMarshal.Fast.cs" />
675675
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\NativeCallableAttribute.cs" />
676+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\NativeLibrary.cs" />
676677
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OptionalAttribute.cs" />
677678
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OutAttribute.cs" />
678679
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PreserveSigAttribute.cs" />
@@ -700,6 +701,7 @@
700701
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector256DebugView_1.cs" />
701702
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Enums.cs" />
702703
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\AssemblyLoadContext.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
704+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\LibraryNameVariation.cs" />
703705
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Remoting\ObjectHandle.cs" />
704706
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\DeserializationBlockedException.cs" />
705707
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\DeserializationToken.cs" />
@@ -1105,6 +1107,7 @@
11051107
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Windows.cs" />
11061108
<Compile Include="$(MSBuildThisFileDirectory)System\IO\DisableMediaInsertionPrompt.cs" />
11071109
<Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.Windows.cs" />
1110+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\LibraryNameVariation.Windows.cs" />
11081111
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Windows.cs" />
11091112
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
11101113
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
@@ -1270,6 +1273,7 @@
12701273
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PersistedFiles.Unix.cs" />
12711274
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PersistedFiles.Names.Unix.cs" />
12721275
<Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.Unix.cs" />
1276+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\LibraryNameVariation.Unix.cs" />
12731277
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Unix.cs" />
12741278
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Unix.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
12751279
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />

src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs renamed to src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeLibrary.cs

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,12 @@ public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearch
8888
throw new ArgumentNullException(nameof(libraryName));
8989
if (assembly == null)
9090
throw new ArgumentNullException(nameof(assembly));
91-
if (!(assembly is RuntimeAssembly))
91+
if (!assembly.IsRuntimeImplemented())
9292
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
9393

94-
return LoadByName(libraryName,
95-
((RuntimeAssembly)assembly).GetNativeHandle(),
96-
searchPath.HasValue,
97-
(uint) searchPath.GetValueOrDefault(),
94+
return LoadLibraryByName(libraryName,
95+
assembly,
96+
searchPath,
9897
throwOnError: true);
9998
}
10099

@@ -114,13 +113,12 @@ public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearc
114113
throw new ArgumentNullException(nameof(libraryName));
115114
if (assembly == null)
116115
throw new ArgumentNullException(nameof(assembly));
117-
if (!(assembly is RuntimeAssembly))
116+
if (!assembly.IsRuntimeImplemented())
118117
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
119118

120-
handle = LoadByName(libraryName,
121-
((RuntimeAssembly)assembly).GetNativeHandle(),
122-
searchPath.HasValue,
123-
(uint) searchPath.GetValueOrDefault(),
119+
handle = LoadLibraryByName(libraryName,
120+
assembly,
121+
searchPath,
124122
throwOnError: false);
125123
return handle != IntPtr.Zero;
126124
}
@@ -200,7 +198,7 @@ public static void SetDllImportResolver(Assembly assembly, DllImportResolver res
200198
throw new ArgumentNullException(nameof(assembly));
201199
if (resolver == null)
202200
throw new ArgumentNullException(nameof(resolver));
203-
if (!(assembly is RuntimeAssembly))
201+
if (!assembly.IsRuntimeImplemented())
204202
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
205203

206204
if (s_nativeDllResolveMap == null)
@@ -245,21 +243,5 @@ internal static IntPtr LoadLibraryCallbackStub(string libraryName, Assembly asse
245243

246244
return resolver(libraryName, assembly, hasDllImportSearchPathFlags ? (DllImportSearchPath?)dllImportSearchPathFlags : null);
247245
}
248-
249-
/// External functions that implement the NativeLibrary interface
250-
251-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
252-
internal static extern IntPtr LoadFromPath(string libraryName, bool throwOnError);
253-
254-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
255-
internal static extern IntPtr LoadByName(string libraryName, RuntimeAssembly callingAssembly,
256-
bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag,
257-
bool throwOnError);
258-
259-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
260-
internal static extern void FreeLib(IntPtr handle);
261-
262-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
263-
internal static extern IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError);
264246
}
265247
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
using System.Collections.Generic;
7+
using System.IO;
8+
9+
namespace System.Runtime.Loader
10+
{
11+
internal partial struct LibraryNameVariation
12+
{
13+
private const string LibraryNamePrefix = "lib";
14+
#if PLATFORM_OSX
15+
private const string LibraryNameSuffix = ".dylib";
16+
#else
17+
private const string LibraryNameSuffix = ".so";
18+
#endif
19+
20+
internal static IEnumerable<LibraryNameVariation> DetermineLibraryNameVariations(string libName, bool isRelativePath)
21+
{
22+
// This is a copy of the logic in DetermineLibNameVariations in dllimport.cpp in CoreCLR
23+
24+
if (!isRelativePath)
25+
{
26+
yield return new LibraryNameVariation(string.Empty, string.Empty);
27+
}
28+
else
29+
{
30+
bool containsSuffix = false;
31+
int indexOfSuffix = libName.IndexOf(LibraryNameSuffix, StringComparison.OrdinalIgnoreCase);
32+
if (indexOfSuffix >= 0)
33+
{
34+
indexOfSuffix += LibraryNameSuffix.Length;
35+
containsSuffix = indexOfSuffix == libName.Length || libName[indexOfSuffix] == '.';
36+
}
37+
38+
bool containsDelim = libName.Contains(Path.DirectorySeparatorChar);
39+
40+
if (containsSuffix)
41+
{
42+
yield return new LibraryNameVariation(string.Empty, string.Empty);
43+
if (!containsDelim)
44+
{
45+
yield return new LibraryNameVariation(LibraryNamePrefix, string.Empty);
46+
}
47+
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
48+
if (!containsDelim)
49+
{
50+
yield return new LibraryNameVariation(LibraryNamePrefix, LibraryNameSuffix);
51+
}
52+
}
53+
else
54+
{
55+
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
56+
if (!containsDelim)
57+
{
58+
yield return new LibraryNameVariation(LibraryNamePrefix, LibraryNameSuffix);
59+
}
60+
yield return new LibraryNameVariation(string.Empty, string.Empty);
61+
if (!containsDelim)
62+
{
63+
yield return new LibraryNameVariation(LibraryNamePrefix, string.Empty);
64+
}
65+
}
66+
}
67+
}
68+
}
69+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
using System.Collections.Generic;
7+
8+
namespace System.Runtime.Loader
9+
{
10+
internal partial struct LibraryNameVariation
11+
{
12+
private const string LibraryNameSuffix = ".dll";
13+
14+
internal static IEnumerable<LibraryNameVariation> DetermineLibraryNameVariations(string libName, bool isRelativePath)
15+
{
16+
// This is a copy of the logic in DetermineLibNameVariations in dllimport.cpp in CoreCLR
17+
18+
yield return new LibraryNameVariation(string.Empty, string.Empty);
19+
20+
if (isRelativePath &&
21+
!libName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) &&
22+
!libName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
23+
{
24+
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
25+
}
26+
}
27+
28+
}
29+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
7+
namespace System.Runtime.Loader
8+
{
9+
internal partial struct LibraryNameVariation
10+
{
11+
public string Prefix;
12+
public string Suffix;
13+
14+
public LibraryNameVariation(string prefix, string suffix)
15+
{
16+
Prefix = prefix;
17+
Suffix = suffix;
18+
}
19+
}
20+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
using System.Reflection;
7+
using System.Runtime.CompilerServices;
8+
using System.Threading;
9+
10+
namespace System.Runtime.InteropServices
11+
{
12+
public static partial class NativeLibrary
13+
{
14+
internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, bool throwOnError)
15+
{
16+
return LoadByName(libraryName,
17+
((RuntimeAssembly)assembly).GetNativeHandle(),
18+
searchPath.HasValue,
19+
(uint) searchPath.GetValueOrDefault(),
20+
throwOnError);
21+
}
22+
23+
/// External functions that implement the NativeLibrary interface
24+
25+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
26+
internal static extern IntPtr LoadFromPath(string libraryName, bool throwOnError);
27+
28+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
29+
internal static extern IntPtr LoadByName(string libraryName, RuntimeAssembly callingAssembly,
30+
bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag,
31+
bool throwOnError);
32+
33+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
34+
internal static extern void FreeLib(IntPtr handle);
35+
36+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
37+
internal static extern IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError);
38+
}
39+
}

src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyDependencyResolver.cs

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public AssemblyDependencyResolver(string componentAssemblyPath)
181181
}
182182

183183
bool isRelativePath = !Path.IsPathFullyQualified(unmanagedDllName);
184-
foreach (LibraryNameVariation libraryNameVariation in DetermineLibraryNameVariations(unmanagedDllName, isRelativePath))
184+
foreach (LibraryNameVariation libraryNameVariation in LibraryNameVariation.DetermineLibraryNameVariations(unmanagedDllName, isRelativePath))
185185
{
186186
string libraryName = libraryNameVariation.Prefix + unmanagedDllName + libraryNameVariation.Suffix;
187187
foreach (string searchPath in searchPaths)
@@ -209,93 +209,10 @@ private static string[] SplitPathsList(string? pathsList)
209209
}
210210
}
211211

212-
private struct LibraryNameVariation
213-
{
214-
public string Prefix;
215-
public string Suffix;
216-
217-
public LibraryNameVariation(string prefix, string suffix)
218-
{
219-
Prefix = prefix;
220-
Suffix = suffix;
221-
}
222-
}
223-
224212
#if PLATFORM_WINDOWS
225213
private const CharSet HostpolicyCharSet = CharSet.Unicode;
226-
private const string LibraryNameSuffix = ".dll";
227-
228-
private IEnumerable<LibraryNameVariation> DetermineLibraryNameVariations(string libName, bool isRelativePath)
229-
{
230-
// This is a copy of the logic in DetermineLibNameVariations in dllimport.cpp in CoreCLR
231-
232-
yield return new LibraryNameVariation(string.Empty, string.Empty);
233-
234-
if (isRelativePath &&
235-
!libName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) &&
236-
!libName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
237-
{
238-
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
239-
}
240-
}
241214
#else
242215
private const CharSet HostpolicyCharSet = CharSet.Ansi;
243-
244-
private const string LibraryNamePrefix = "lib";
245-
#if PLATFORM_OSX
246-
private const string LibraryNameSuffix = ".dylib";
247-
#else
248-
private const string LibraryNameSuffix = ".so";
249-
#endif
250-
251-
private IEnumerable<LibraryNameVariation> DetermineLibraryNameVariations(string libName, bool isRelativePath)
252-
{
253-
// This is a copy of the logic in DetermineLibNameVariations in dllimport.cpp in CoreCLR
254-
255-
if (!isRelativePath)
256-
{
257-
yield return new LibraryNameVariation(string.Empty, string.Empty);
258-
}
259-
else
260-
{
261-
bool containsSuffix = false;
262-
int indexOfSuffix = libName.IndexOf(LibraryNameSuffix, StringComparison.OrdinalIgnoreCase);
263-
if (indexOfSuffix >= 0)
264-
{
265-
indexOfSuffix += LibraryNameSuffix.Length;
266-
containsSuffix = indexOfSuffix == libName.Length || libName[indexOfSuffix] == '.';
267-
}
268-
269-
bool containsDelim = libName.Contains(Path.DirectorySeparatorChar);
270-
271-
if (containsSuffix)
272-
{
273-
yield return new LibraryNameVariation(string.Empty, string.Empty);
274-
if (!containsDelim)
275-
{
276-
yield return new LibraryNameVariation(LibraryNamePrefix, string.Empty);
277-
}
278-
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
279-
if (!containsDelim)
280-
{
281-
yield return new LibraryNameVariation(LibraryNamePrefix, LibraryNameSuffix);
282-
}
283-
}
284-
else
285-
{
286-
yield return new LibraryNameVariation(string.Empty, LibraryNameSuffix);
287-
if (!containsDelim)
288-
{
289-
yield return new LibraryNameVariation(LibraryNamePrefix, LibraryNameSuffix);
290-
}
291-
yield return new LibraryNameVariation(string.Empty, string.Empty);
292-
if (!containsDelim)
293-
{
294-
yield return new LibraryNameVariation(LibraryNamePrefix, string.Empty);
295-
}
296-
}
297-
}
298-
}
299216
#endif
300217

301218
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = HostpolicyCharSet)]

0 commit comments

Comments
 (0)