Skip to content

Commit eeed7e2

Browse files
committed
[release/7.0.2xx-xcode14.2] [tests] Find a workaround for #xamarin/maccore@2668.
1. Mono changed dyld lookup to start looking in directories in NATIVE_DLL_SEARCH_DIRECTORIES before the actual given path, even when the given path is absolute [1]. 2. This turned out to break Mac Catalyst, because when a DllImport says a P/Invoke is in "/System/Library/Frameworks/SceneKit.framework/SceneKit", Mono would try loading by prefixing the directories in NATIVE_DLL_SEARCH_DIRECTORIES. We add the Contents/MonoBundle directory to NATIVE_DLL_SEARCH_DIRECTORIES, so Mono would try to load "/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit", and things would go wrong. 3. We found a workaround: add "/" to NATIVE_DLL_SEARCH_DIRECTORIES. This works on Ventura, but apparently not on older macOS version, because the actual path we pass to dlopen ends up being "///System/Library/Frameworks/SceneKit.framework/SceneKit" (note the three initial slashes instead of a single slash). 4. Add a second workaround, where we add a dll import resolver to load exactly the path we want to load. [1]: dotnet/runtime@5a1baeb [2]: dotnet/runtime#85255 Technical sidenote: Why trying to load "/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit" turned out so bad on Mac Catalyst is not obvious. What happens is this: * The app calls 'dlopen ("/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit")' * dlopen checks if this is a Mac Catalyst override of a macOS system framework, by prefixing "/System/iOSSupport" and trying to load that. So dlopen would try to load "/System/iOSSupport/path/to/my.app/Contents/MonoBundle//System/Library/Frameworks/SceneKit.framework/SceneKit", which would obviously fail. * Then dlopen would try a few more fallbacks, eventually trying "/System/Library/Frameworks/SceneKit.framework/SceneKit", and successfully loading that library. * Unfortunately "/System/Library/Frameworks/SceneKit.framework/SceneKit" is the wrong library to load for Mac Catalyst ("/System/iOSSupport/System/Library/Frameworks/SceneKit.framework/SceneKit" is the correct version). These two libraries are incompatible, and calling one when you mean to call the other will do nasty things like corrupting the stack. Backport of dotnet#18159.
1 parent b577489 commit eeed7e2

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

tests/common/AppDelegate.cs

+25
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Reflection;
5+
using System.Runtime.InteropServices;
6+
using System.Text;
57

8+
using ObjCRuntime;
69
using Foundation;
710
#if !__MACOS__
811
using UIKit;
@@ -48,9 +51,31 @@ public override bool FinishedLaunching (UIApplication application, NSDictionary
4851
public static class MainClass {
4952
static void Main (string [] args)
5053
{
54+
#if __MACCATALYST__
55+
NativeLibrary.SetDllImportResolver (typeof (NSObject).Assembly, DllImportResolver);
56+
NativeLibrary.SetDllImportResolver (typeof (MainClass).Assembly, DllImportResolver);
57+
#endif
5158
#if !__MACOS__
5259
UIApplication.Main (args, null, typeof (AppDelegate));
5360
#endif
5461
}
62+
63+
#if __MACCATALYST__
64+
// This is a workaround for a temporary issue in the .NET runtime
65+
// See https://github.com/xamarin/maccore/issues/2668
66+
// The issue is present in .NET 7.0.5, and will likely be fixed in .NET 7.0.6.
67+
static IntPtr DllImportResolver (string libraryName, global::System.Reflection.Assembly assembly, DllImportSearchPath? searchPath)
68+
{
69+
switch (libraryName) {
70+
case "/System/Library/Frameworks/SceneKit.framework/SceneKit":
71+
case "/System/Library/Frameworks/SceneKit.framework/Versions/A/SceneKit":
72+
var rv = NativeLibrary.Load (libraryName);
73+
Console.WriteLine ($"DllImportResolver callback loaded library \"{libraryName}\" from a P/Invoke in \"{assembly}\" => 0x{rv.ToString ("x")}");
74+
return rv;
75+
default:
76+
return IntPtr.Zero;
77+
}
78+
}
79+
#endif
5580
}
5681
#endif // !__WATCHOS__

0 commit comments

Comments
 (0)