问题
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.
回答1:
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.Is64BitOperatingSystem)
{
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();
}
回答2:
Since you have not provided any code snippets which would show your usage of DllImportAttribute
or any other environment initialization that your application might do then it is really difficult to hazard any guesses on what exactly could be going wrong.
With the information available the most likely culprit is simply that the P/Invoke system does not know how to find your native library. Does your codebase have some sort of mechanism to add search paths to the runtime? Or are you per-chance using a custom load context?
来源:https://stackoverflow.com/questions/58955723/net-core-project-with-native-library-depedency