I am writing an app in .NET Core that depends on native code using [DllImport]
. I have the native compiled library artifacts for win-x64, win-x86, and linux-x64.
My project structure is like:
MyApp
|--Main.cs
|--runtimes
|--win-x86
|--native
|--somelibrary.dll
|--win-x64
|--native
|--somelibrary.dll
|--linux-x64
|--native
|--libsomelibrary.so
I get then DLL not found exceptions when I run the app.
I have tried to use MSBuild targets solution here, but this only copies one dll
to the main output folder at compile time. However, I want to the output to include all three native libraries in the output folder in the same structure as the runtimes folder above, and leave the selection of the compatible native library to .NET Core runtime host.
So if the user runs the app in Windows x86, it will use the win-x86, and so on.
I have noticed when I reference native wrappers like SkiaSharp from NuGet, it will actually integrate nicely into my app, and will include all assets in a runtimes folder structure to work on multiple environments at runtime. How can I do this?
Edit:
I ended up creating a nuget package for the native library binding, and reference the nuget in my other projects.
This should copy your folder structure to the output folder, just put it right away under the first </PropertyGroup>
in your MyApp.csproj
:
<ItemGroup>
<None Update="runtimes\**" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
Just in case, there is a method to have more control on how you are loading the native libraries using DllImport
by DllImportResolver
delegate for your assembly.
public delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);
There is also NativeLibrary
class which allows to set and load native libraries for .net core. Some sample code:
static class Sample
{
const string NativeLib = "NativeLib";
static Sample()
{
NativeLibrary.SetDllImportResolver(typeof(Sample).Assembly, ImportResolver);
}
private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
IntPtr libHandle = IntPtr.Zero;
//you can add here different loading logic
if (libraryName == NativeLib && RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.Is64BitProcess)
{
NativeLibrary.TryLoad("./runtimes/win-x64/native/somelib.dll", out libHandle);
} else
if (libraryName == NativeLib)
{
NativeLibrary.TryLoad("libsomelibrary.so", assembly, DllImportSearchPath.ApplicationDirectory, out libHandle);
}
return libHandle;
}
[DllImport(NativeLib)]
public static extern int DoSomework();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With