We are ploughing through the upgrade of our codebase to .net 7.
Our plugin uses some Native C++ DLL’s which reside in \runtimes\win-x64\native\ - a subfolder from where our .rhp file is.
Unfortunately they are not resolved when our plugin loads.
If i copy our dll’s into C:\Program Files\Rhino 8\System\netcore\runtimes\win-x64\native then the dll’s are found and the plugin loads.
I assume that the root cause here is that we are using Rhino’s “runtime” of .net rather than our plugin. So our plugin is not in the search path
Is there a mechanism i can use to tell the runtime where to load the dll from? or add a path to the load system?
Dit it work before, or does it still work with .net4.8?
How are the native DLLs used in your plug-in? If with P/invoke, maybe you could set the relative path in the DllImport statement?
Thanks @menno yeah it works nicely with .net 4.8 in both Rhion 7 & 8.
The native library is a dependency of a dependency so I do not have control of the load point.
I found a workaround - one solution is to use a NativeLibrary.SetDllImportResolver see documentation here.
This allows you to prompt the .net runtime with the path of the dll’s on disk.
The tricky part is that these resolvers have to be added to each assembly (dll) in your project which needs to resolve the dll. In our case I had to add a resolver to one of our dependencies also.
Maybe there is a more elegant or global solution to add the path.
Anyway I leave my code below in case anyone runs into this.
It is specific to loading OpenCVSharp but should be easy enough to modify
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Dalmatian;
public static class OpenCVResolver {
private static string _assemblyLocation = string.Empty;
private const string RuntimeFolder64 = @"\runtimes\win-x64\native\";
private const string RuntimeFolder86 = @"\runtimes\win-x86\native\";
public static void Start() {
// first find out where our plugin lives on disk
var executingAssembly = Assembly.GetExecutingAssembly();
_assemblyLocation = Path.GetDirectoryName(executingAssembly.Location);
// then add a resolver to both our plugin dll and to OpenCVSharp.dll
NativeLibrary.SetDllImportResolver(executingAssembly, Resolver);
var opencv = Assembly.GetAssembly(typeof(OpenCvSharp.Cv2));
if (opencv != null) {
NativeLibrary.SetDllImportResolver(opencv, Resolver);
}
}
private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) {
if (libraryName.Contains("opencv", StringComparison.InvariantCultureIgnoreCase)) {
var proposedPath = _assemblyLocation
+ (Environment.Is64BitProcess ? RuntimeFolder64 : RuntimeFolder86)
+ libraryName + ".dll";
if (File.Exists(proposedPath)) {
return NativeLibrary.Load(proposedPath, assembly, searchPath);
}
}
return IntPtr.Zero;
}
}