Problem loading librhino3dm_native on Mac Rhino 8

I am developing a plugin for Rhino 8 and Mac which uses Rhino3dm 8.0.1. The following exception happens when the assembly gets used by the application the first time:

Exception has occurred: CLR/System.DllNotFoundException
An exception of type 'System.DllNotFoundException' occurred in Rhino3dm.dll but was not handled in user code: 'Unable to load shared library 'librhino3dm_native' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: 
dlopen(/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native.dylib, 0x0001): tried: '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native.dylib' (no such file), '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native.dylib' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native.dylib' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native.dylib' (no such file)
dlopen(librhino3dm_native.dylib, 0x0001): tried: 'librhino3dm_native.dylib' (relative path not allowed in hardened program), '/System/Volumes/Preboot/Cryptexes/OSlibrhino3dm_native.dylib' (no such file), '/Applications/Rhino 8.app/Contents/Frameworks/librhino3dm_native.dylib' (no such file), '/usr/lib/librhino3dm_native.dylib' (no such file, not in dyld cache), 'librhino3dm_native.dylib' (relative path not allowed in hardened program), '/usr/lib/librhino3dm_native.dylib' (no such file, not in dyld cache)
dlopen(/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native.dylib, 0x0001): tried: '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native.dylib' (no such file), '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native.dylib' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native.dylib' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native.dylib' (no such file)
dlopen(liblibrhino3dm_native.dylib, 0x0001): tried: 'liblibrhino3dm_native.dylib' (relative path not allowed in hardened program), '/System/Volumes/Preboot/Cryptexes/OSliblibrhino3dm_native.dylib' (no such file), '/Applications/Rhino 8.app/Contents/Frameworks/liblibrhino3dm_native.dylib' (no such file), '/usr/lib/liblibrhino3dm_native.dylib' (no such file, not in dyld cache), 'liblibrhino3dm_native.dylib' (relative path not allowed in hardened program), '/usr/lib/liblibrhino3dm_native.dylib' (no such file, not in dyld cache)
dlopen(/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native, 0x0001): tried: '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native' (no such file), '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/librhino3dm_native' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/librhino3dm_native' (no such file)
dlopen(librhino3dm_native, 0x0001): tried: 'librhino3dm_native' (relative path not allowed in hardened program), '/System/Volumes/Preboot/Cryptexes/OSlibrhino3dm_native' (no such file), '/Applications/Rhino 8.app/Contents/Frameworks/librhino3dm_native' (no such file), '/usr/lib/librhino3dm_native' (no such file, not in dyld cache), 'librhino3dm_native' (relative path not allowed in hardened program), '/usr/lib/librhino3dm_native' (no such file, not in dyld cache)
dlopen(/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native, 0x0001): tried: '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native' (no such file), '/Users/axl/Library/Application Support/McNeel/Rhinoceros/packages/8.0/LocalDevelopment/1.17.0/liblibrhino3dm_native' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native' (no such file), '/Users/axl/Arbeit/ShapeDiver/dev/worker/ShapeDiverGrasshopperPlugin/bin/Deploy/net7.0-macos/liblibrhino3dm_native' (no such file)
dlopen(liblibrhino3dm_native, 0x0001): tried: 'liblibrhino3dm_native' (relative path not allowed in hardened program), '/System/Volumes/Preboot/Cryptexes/OSliblibrhino3dm_native' (no such file), '/Applications/Rhino 8.app/Contents/Frameworks/liblibrhino3dm_native' (no such file), '/usr/lib/liblibrhino3dm_native' (no such file, not in dyld cache), 'liblibrhino3dm_native' (relative path not allowed in hardened program), '/usr/lib/liblibrhino3dm_native' (no such file, not in dyld cache)'
   at UnsafeNativeMethods.ONX_Model_New()
   at Rhino.FileIO.File3dm..ctor()

The library is there in my build output folder, in the runtime folder:

@snabela Is this something that worked before with previous versions of rhino3dm?

I tested this, the problem also happens when using Rhino3dm 7.15.0 and building for <TargetFramework>net7.0-macos</TargetFramework>.

My suspicion: So far this problem did not pop up for us, because for Mac Rhino 7 we are shipping the same plugin built for <TargetFramework>net48</TargetFramework>.

Hey @snabela, this is related to RH-80178, where we need to use the .NET Core resolver to resolve managed and native assemblies in the runtimes\ folder for plugins.

Some have resolved this currently by loading their assemblies in their own AssemblyLoadContext with the proper resolver in place, or you could load the native library manually before any code that uses it is required.

We have others that are running into this issue as well, so this is pretty high on our priority list.

Hope this helps.
Curtis.

1 Like

Why are you using Rhino3dm in a plugin? Every piece of functionality should be available from RhinoCommon.

3 Likes

Hi @curtisw, I believe I’m running into the same issue. My plugin leverages a native mesh class which I pinvoke from an external DLL:

        [DllImport("MRMesh.dll", CallingConvention = CallingConvention.Cdecl)]
        internal unsafe static extern IntPtr CreateMeshFromPointers(Point3f* vertices, int vertexCount, int* faces, int faceCount);

There are approx. 20 more DLLs referenced by this package. All works fine in Rhino 7 .NET Framework 4.8 but Rhino 8 fails to resolve the reference:

Exception thrown: 'System.DllNotFoundException' in HLA_Core.dll
An exception of type 'System.DllNotFoundException' occurred in HLA_Core.dll but was not handled in user code
Unable to load DLL 'MRMesh.dll' or one of its dependencies: The specified procedure could not be found. (0x8007007F)

How would you suggest to address this?
[EDIT for clarity] The plugin is currently Windows-only

Hey @mrhe,

Sorry to hear you’re having troubles. Do you have a copy of your plugin (and/or source to an example) that you can send via Rhino - Upload to Support? I can take a look into why it might be failing. Enter curtis@mcneel.com for the email address so I can see it.

Cheers,
Curtis.

Some code that helped me solve this:

        /// <inheritdoc/>
        public void LoadNativeLibrary(string library)
        {
#if NET6_0_OR_GREATER
            var thisAssemblyPath = Path.GetDirectoryName(typeof(IocContainerSingleton).Assembly.Location);
            var architecture = GetArchitecture();
            if (architecture == null)
                throw new Exception("Could not determine architecture of current system.");
            var extension = architecture.StartsWith("win") ? "dll" : architecture.StartsWith("linux") ? "so" : "dylib";
            NativeLibrary.Load(Path.Combine(thisAssemblyPath, "runtimes", GetArchitecture(), $"native/{library}.{extension}"));
#endif
        }

        /// <inheritdoc/>
        public void LoadNativeLibraries(IEnumerable<string> libraries)
        {
            if (libraries == null)
                return;
            foreach (var library in libraries)
            {
                LoadNativeLibrary(library);
            }
        }

        /// <inheritdoc/>
        public string GetArchitecture()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                if (Environment.Is64BitOperatingSystem)
                {
                    return "win-x64";
                }
                else
                {
                    return "win-x86";
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                if (RuntimeInformation.OSArchitecture == Architecture.Arm64)
                {
                    return "linux-arm64";
                }
                else if (RuntimeInformation.OSArchitecture == Architecture.X64)
                {
                    return "linux-x64";
                }
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                if (RuntimeInformation.OSArchitecture == Architecture.Arm64)
                {
                    return "osx-arm64";
                }
                else if (RuntimeInformation.OSArchitecture == Architecture.X64)
                {
                    return "osx-x64";
                }
            }

            return null;
        }

Call LoadNativeLibrary("librhino3dm_native") before using Rhino3dm.

@curtisw did I understand correctly that this will be handled by Rhino3dm automatically in the future?