3

I have native unmanaged dll which is static and must be loaded each time when I need library to do some work if i want to run it in parallel. In .NET I would use AppDomain and load this dll when i need it, but in NET Core AppDomains are gone (for now). I have looked at AssemblyLoadContext but there is no proper documentation with LoadUnmanagedDll. Can this be done in netstandard1.6?

Edit Currently code is called with PInvoke and is working perfectly. Problem is because nature of this unmanged dll, when I try to call it in parallel throws AccessViolationException because two or more task wants to access same memory.

If I could load dll for each time that in some context and then call PInvoke on that this problem would be gone.

user1646245
  • 309
  • 4
  • 8
  • AppDomains are windows only. Since .net core runs on windows and unix based systems you have to use other means to load the unmanaged library (e.g. PInvoke) – Sebastian L Mar 27 '17 at 14:42
  • You can use PInvoke for load unmanaged library. It's works fine for mono and most likely works for net core. As example you can see my old question: http://stackoverflow.com/questions/42977306/convert-unmanaged-c-pointer-to-an-object-to-a-managed-c-sharp-object – Ivan Kishchenko Mar 27 '17 at 14:43
  • @IvanKishchenko, please look at edited question. – user1646245 Mar 27 '17 at 15:04
  • It might be just easier to fix your native library to allow multiple and/or multi-threaded access. – omajid Mar 27 '17 at 22:50
  • @omajid Library is quite complex and I can't chage source code. Thanks anyway. – user1646245 Mar 28 '17 at 13:59
  • Write an own helper executable project. The executable loads the DLL and then hosts an interface to access functions in the DLL. When your main project needs access to functions in the DLL, it starts an instance of the helper executable and uses interprocess communication to talk with it. -> Every instance of the DLL is loaded in a separate process. – NineBerry Sep 12 '18 at 01:52

1 Answers1

6

One approach:

  1. Derive class from System.Runtime.Loader.AssemblyLoadContext
  2. Override Load(AssemblyName assemblyName) calling LoadFromAssemblyPath() or returning null to fallback on default context
  3. Override IntPtr LoadUnmanagedDll(string unmanagedDllName) calling LoadUnmanagedDllFromPath() to load your native dll
  4. Indirectly access your pinvoke methods and load the native/unmanaged library through some known interface

Step 4 is the part you need to adjust based on the structure of the existing code. In my case, I created 3 assemblies:

  1. Calling code
  2. Pinvoke code
  3. Interfaces shared by the first two

In the calling code:

var assem = assemblyLoadContext.LoadFromAssemblyName(new 
System.Reflection.AssemblyName(pinvokeAssemblyName));
var type = assem.GetType(nameOfTypeThatCallsPinvoke);
return (ISharedInterface)Activator.CreateInstance(type);

When instance of nameOfTypeThatCallsPinvoke attempts to use pinvoke method your LoadUnmanagedDll() override on the load context will get called.

The shared interfaces are needed so types are known at compile-time. If the calling code references the pinvoke library directly it's types will differ from those obtained through the load context.

References:

Jake
  • 1,304
  • 9
  • 11