[objcruntime] Refactor `Dlfcn.dlopen` to ease linking (#12002)
* Skip extraneous logic for generated entries where we know the full path is available * Update generator to use the internal `_dlopen` that skips the checks * This removes the code below (diff) for a simple application * Use the linker substitution files to remove the warning on release builds * If `dlopen` is used then `WarnOnce` method becomes a empty stub and * field `warningShown` is also removed ```diff --- a.cs 2021-06-22 20:59:25.000000000 -0400 +++ b.cs 2021-06-22 20:59:28.000000000 -0400 @@ -2023,44 +2023,14 @@ { public static class System { - public static readonly IntPtr Handle = Dlfcn.dlopen("/usr/lib/libSystem.dylib", 0); + public static readonly IntPtr Handle = Dlfcn._dlopen("/usr/lib/libSystem.dylib", 0); } } public static class Dlfcn { - private static bool warningShown; - [DllImport("/usr/lib/libSystem.dylib", EntryPoint = "dlopen")] internal static extern IntPtr _dlopen(string P_0, int P_1); - public static IntPtr dlopen(string P_0, int P_1) - { - return dlopen(P_0, P_1, true); - } - - internal static IntPtr dlopen(string P_0, int P_1, bool P_2) - { - IntPtr intPtr = _dlopen(P_0, P_1); - if (intPtr != IntPtr.Zero) - { - return intPtr; - } - if (P_0.IndexOf('/') == -1) - { - if (!warningShown && P_2) - { - Runtime.NSLog("You are using dlopen without a full path, retrying by prepending /usr/lib"); - warningShown = true; - } - intPtr = _dlopen("/usr/lib/" + P_0, P_1); - if (intPtr != IntPtr.Zero) - { - return intPtr; - } - } - return IntPtr.Zero; - } - [DllImport("/usr/lib/libSystem.dylib")] public static extern IntPtr dlsym(IntPtr P_0, string P_1); } ``` Co-authored-by: Sebastien Pouliot <sebastien.pouliot@microsoft.com>
This commit is contained in:
Родитель
096c75f425
Коммит
7b934c811c
|
@ -1,5 +1,8 @@
|
|||
<linker>
|
||||
<assembly fullname="Xamarin.iOS">
|
||||
<type fullname="ObjCRuntime.Dlfcn">
|
||||
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
|
||||
</type>
|
||||
<type fullname="ObjCRuntime.Runtime">
|
||||
<method signature="System.Boolean get_IsCoreCLR()" body="stub" value="false" />
|
||||
</type>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
<linker>
|
||||
<assembly fullname="Xamarin.TVOS">
|
||||
<type fullname="ObjCRuntime.Dlfcn">
|
||||
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
|
||||
</type>
|
||||
<type fullname="ObjCRuntime.Runtime">
|
||||
<method signature="System.Boolean get_IsCoreCLR()" body="stub" value="false" />
|
||||
</type>
|
||||
|
|
|
@ -49,20 +49,20 @@ namespace ObjCRuntime {
|
|||
static partial class Libraries {
|
||||
#if !COREBUILD
|
||||
static public class System {
|
||||
static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.libSystemLibrary, 0);
|
||||
static public readonly IntPtr Handle = Dlfcn._dlopen (Constants.libSystemLibrary, 0);
|
||||
}
|
||||
static public class LibC {
|
||||
static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.libcLibrary, 0);
|
||||
static public readonly IntPtr Handle = Dlfcn._dlopen (Constants.libcLibrary, 0);
|
||||
}
|
||||
#if HAS_OPENGLES
|
||||
static public class OpenGLES
|
||||
{
|
||||
static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.OpenGLESLibrary, 0);
|
||||
static public readonly IntPtr Handle = Dlfcn._dlopen (Constants.OpenGLESLibrary, 0);
|
||||
}
|
||||
#endif
|
||||
#if !WATCH
|
||||
static public class AudioToolbox {
|
||||
static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.AudioToolboxLibrary, 0);
|
||||
static public readonly IntPtr Handle = Dlfcn._dlopen (Constants.AudioToolboxLibrary, 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -98,10 +98,18 @@ namespace ObjCRuntime {
|
|||
|
||||
public static IntPtr dlopen (string path, int mode)
|
||||
{
|
||||
return dlopen (path, mode, true);
|
||||
return dlopen (path, mode, showWarning: true);
|
||||
}
|
||||
|
||||
static bool warningShown;
|
||||
// the linker can eliminate the body of this method (and the above static variable) on release builds
|
||||
static void WarnOnce ()
|
||||
{
|
||||
if (!warningShown)
|
||||
Runtime.NSLog ("You are using dlopen without a full path, retrying by prepending /usr/lib");
|
||||
warningShown = true;
|
||||
}
|
||||
|
||||
internal static IntPtr dlopen (string path, int mode, bool showWarning)
|
||||
{
|
||||
var x = _dlopen (path, mode);
|
||||
|
@ -112,14 +120,9 @@ namespace ObjCRuntime {
|
|||
// In iOS >= 9, this fails with:
|
||||
// "no cache image with name (<top>)"
|
||||
if (path.IndexOf ('/') == -1){
|
||||
if (!warningShown && showWarning) {
|
||||
Runtime.NSLog ("You are using dlopen without a full path, retrying by prepending /usr/lib");
|
||||
warningShown = true;
|
||||
}
|
||||
|
||||
x = _dlopen ("/usr/lib/" + path, mode);
|
||||
if (x != IntPtr.Zero)
|
||||
return x;
|
||||
if (showWarning)
|
||||
WarnOnce ();
|
||||
return dlopen ("/usr/lib/" + path, mode, false);
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
|
|
@ -2745,8 +2745,12 @@ public partial class Generator : IMemberGatherer {
|
|||
print ("static public readonly IntPtr Handle = Dlfcn.dlopen (null, 0);");
|
||||
} else if (BindThirdPartyLibrary && library_path != null && IsNotSystemLibrary (library_name)) {
|
||||
print ($"static public readonly IntPtr Handle = Dlfcn.dlopen (\"{library_path}\", 0);");
|
||||
} else {
|
||||
} else if (BindThirdPartyLibrary) {
|
||||
print ("static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.{0}Library, 0);", library_name);
|
||||
} else {
|
||||
// Skip the path check that our managed `dlopen` method does
|
||||
// This is not required since the path is checked by `IsNotSystemLibrary`
|
||||
print ("static public readonly IntPtr Handle = Dlfcn._dlopen (Constants.{0}Library, 0);", library_name);
|
||||
}
|
||||
indent--; print ("}");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче