Use NativeLibrary.[Try]Load for netcoreapp3 (dotnet/corefx#36944)
authorAdeel Mujahid <adeelbm@outlook.com>
Wed, 17 Apr 2019 18:44:46 +0000 (19:44 +0100)
committerJan Kotas <jkotas@microsoft.com>
Wed, 17 Apr 2019 18:44:46 +0000 (11:44 -0700)
Commit migrated from https://github.com/dotnet/corefx/commit/fbc748b93e65600a68b217ec59fc4522d5df4ffb

src/libraries/Common/src/System/Runtime/InteropServices/FunctionWrapper.cs
src/libraries/CoreFx.Private.TestUtilities/src/System/PlatformDetection.Unix.cs
src/libraries/System.Data.Odbc/tests/System.Data.Odbc.Tests.csproj
src/libraries/System.Drawing.Common/src/System.Drawing.Common.csproj
src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Unix.cs
src/libraries/System.Drawing.Common/src/System/Drawing/Printing/LibcupsNative.cs

index 9b56ef3..af0f815 100644 (file)
@@ -65,6 +65,7 @@ namespace System.Runtime.InteropServices
                     return new FunctionLoadResult<T>(FunctionLoadResultKind.LibraryNotFound, null);
                 }
 
+#if netcoreapp20
                 IntPtr funcPtr = LoadFunctionPointer(nativeLibraryHandle, funcName);
                 if (funcPtr == IntPtr.Zero)
                 {
@@ -74,6 +75,11 @@ namespace System.Runtime.InteropServices
                 {
                     return new FunctionLoadResult<T>(FunctionLoadResultKind.Success, Marshal.GetDelegateForFunctionPointer<T>(funcPtr));
                 }
+#else // use managed NativeLibrary API from .NET Core 3 onwards
+                return NativeLibrary.TryGetExport(nativeLibraryHandle, funcName, out var funcPtr)
+                    ? new FunctionLoadResult<T>(FunctionLoadResultKind.Success, Marshal.GetDelegateForFunctionPointer<T>(funcPtr))
+                    : new FunctionLoadResult<T>(FunctionLoadResultKind.FunctionNotFound, null);
+#endif
             });
 
             return new FunctionWrapper<T>(lazyDelegate, libName, funcName);
index 8b0530d..541b417 100644 (file)
@@ -65,20 +65,20 @@ namespace System
 
         public static bool IsDrawingSupported { get; } =
             RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
-#if netcoreapp30
-                ? NativeLibrary.TryLoad("libgdiplus.dylib", out _)
-                : NativeLibrary.TryLoad("libgdiplus.so", out _) || NativeLibrary.TryLoad("libgdiplus.so.0", out _);
-#else
+#if netcoreapp20
                 ? dlopen("libgdiplus.dylib", RTLD_LAZY) != IntPtr.Zero
                 : dlopen("libgdiplus.so", RTLD_LAZY) != IntPtr.Zero || dlopen("libgdiplus.so.0", RTLD_LAZY) != IntPtr.Zero;
 
-        public static bool IsInContainer => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && File.Exists("/.dockerenv");
-
         [DllImport("libdl")]
         private static extern IntPtr dlopen(string libName, int flags);
         private const int RTLD_LAZY = 0x001;
+#else // use managed NativeLibrary API from .NET Core 3 onwards
+                ? NativeLibrary.TryLoad("libgdiplus.dylib", out _)
+                : NativeLibrary.TryLoad("libgdiplus.so", out _) || NativeLibrary.TryLoad("libgdiplus.so.0", out _);
 #endif
 
+        public static bool IsInContainer => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && File.Exists("/.dockerenv");
+
         public static bool IsSoundPlaySupported { get; } = false;
 
         public static Version OSXVersion { get; } = ToVersion(PlatformApis.GetOSVersion());
index b74ad0b..f3cc82e 100644 (file)
@@ -20,7 +20,7 @@
     <Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
       <Link>Common\Interop\Unix\Interop.Libraries.cs</Link>
     </Compile>
-    <Compile Include="$(CommonPath)\Interop\Unix\libdl\Interop.dlopen.cs">
+    <Compile Include="$(CommonPath)\Interop\Unix\libdl\Interop.dlopen.cs" Condition="'$(TargetGroup)' == 'netcoreapp2.0'">
       <Link>Common\Interop\Unix\libdl\Interop.dlopen.cs</Link>
     </Compile>
   </ItemGroup>
index b94a8fb..776b14a 100644 (file)
     <Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
       <Link>Common\Interop\Unix\Interop.Libraries.cs</Link>
     </Compile>
+    <EmbeddedResource Include="Resources\System\Drawing\Error.ico">
+      <LogicalName>placeholder.ico</LogicalName>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp2.0' AND '$(TargetsUnix)' == 'true'">
     <Compile Include="$(CommonPath)\Interop\Unix\libdl\Interop.dlopen.cs">
       <Link>Common\Interop\Unix\libdl\Interop.dlopen.cs</Link>
     </Compile>
     <Compile Include="$(CommonPath)\System\Runtime\InteropServices\FunctionWrapper.Unix.cs">
       <Link>Common\System\Runtime\InteropServices\FunctionWrapper.Unix.cs</Link>
     </Compile>
-    <EmbeddedResource Include="Resources\System\Drawing\Error.ico">
-      <LogicalName>placeholder.ico</LogicalName>
-    </EmbeddedResource>
   </ItemGroup>
   <ItemGroup Condition="'$(TargetsNetFx)' != 'true'">
     <Reference Include="Microsoft.Win32.Primitives" />
index c0489be..5c956fc 100644 (file)
@@ -32,7 +32,13 @@ namespace System.Drawing
                 if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                 {
                     libraryName = "libgdiplus.dylib";
+
+#if netcoreapp20
                     lib = Interop.Libdl.dlopen(libraryName, Interop.Libdl.RTLD_LAZY);
+#else // use managed NativeLibrary API from .NET Core 3 onwards
+                    var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+                    NativeLibrary.TryLoad(libraryName, assembly, default, out lib);
+#endif
                 }
                 else
                 {
@@ -41,13 +47,23 @@ namespace System.Drawing
                     // a global configuration setting. We prefer the "unversioned" shared object name, and fallback to
                     // the name suffixed with ".0".
                     libraryName = "libgdiplus.so";
+
+#if netcoreapp20
                     lib = Interop.Libdl.dlopen(libraryName, Interop.Libdl.RTLD_LAZY);
                     if (lib == IntPtr.Zero)
                     {
                         lib = Interop.Libdl.dlopen("libgdiplus.so.0", Interop.Libdl.RTLD_LAZY);
                     }
+#else // use managed NativeLibrary API from .NET Core 3 onwards
+                    var assembly = System.Reflection.Assembly.GetExecutingAssembly();
+                    if (!NativeLibrary.TryLoad(libraryName, assembly, default, out lib))
+                    {
+                         NativeLibrary.TryLoad("libgdiplus.so.0", assembly, default, out lib);
+                    }
+#endif
                 }
 
+#if netcoreapp20
                 // If we couldn't find libgdiplus in the system search path, try to look for libgdiplus in the
                 // NuGet package folders. This matches the DllImport behavior.
                 if (lib == IntPtr.Zero)
@@ -59,21 +75,19 @@ namespace System.Drawing
                         var searchPath = Path.Combine(searchDirectory, libraryName);
 
                         lib = Interop.Libdl.dlopen(searchPath, Interop.Libdl.RTLD_LAZY);
-
                         if (lib != IntPtr.Zero)
                         {
                             break;
                         }
                     }
                 }
+#endif
 
                 // This function may return a null handle. If it does, individual functions loaded from it will throw a DllNotFoundException,
                 // but not until an attempt is made to actually use the function (rather than load it). This matches how PInvokes behave.
                 return lib;
             }
 
-            private static IntPtr LoadFunctionPointer(IntPtr nativeLibraryHandle, string functionName) => Interop.Libdl.dlsym(nativeLibraryHandle, functionName);
-
             private static void PlatformInitialize()
             {
                 LoadFunctionPointers();
index cff2025..6f0899f 100644 (file)
@@ -15,12 +15,18 @@ namespace System.Drawing.Printing
         private static IntPtr LoadLibcups()
         {
             // We allow both "libcups.so" and "libcups.so.2" to be loaded.
+#if netcoreapp20
             IntPtr lib = Interop.Libdl.dlopen("libcups.so", Interop.Libdl.RTLD_LAZY);
             if (lib == IntPtr.Zero)
             {
                 lib = Interop.Libdl.dlopen("libcups.so.2", Interop.Libdl.RTLD_LAZY);
             }
-
+#else // use managed NativeLibrary API from .NET Core 3 onwards
+            if (!NativeLibrary.TryLoad("libcups.so", out IntPtr lib))
+            {
+                NativeLibrary.TryLoad("libcups.so.2", out lib);
+            }
+#endif
             return lib;
         }