具有本机库依赖的 .NET Core 项目

Gha*_*san 7 cross-platform native .net-core

我正在 .NET Core 中编写一个应用程序,该应用程序依赖于使用[DllImport]. 我有适用于 win-x64、win-x86 和 linux-x64 的本地编译库工件。

我的项目结构是这样的:

MyApp
|--Main.cs
|--runtimes
   |--win-x86
      |--native
         |--somelibrary.dll
   |--win-x64
      |--native
         |--somelibrary.dll
   |--linux-x64
      |--native
         |--libsomelibrary.so
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序时,我得到了 DLL not found 异常。

我曾尝试在此处使用 MSBuild 目标解决方案,但这仅dll在编译时将一个复制到主输出文件夹。但是,我希望输出以与上面的 runtimes 文件夹相同的结构在输出文件夹中包含所有三个本机库,并将兼容本机库的选择留给 .NET Core 运行时主机。

因此,如果用户在 Windows x86 中运行该应用程序,它将使用 win-x86,依此类推。

我注意到,当我从 NuGet引用像SkiaSharp这样的原生包装器时,它实际上会很好地集成到我的应用程序中,并将包含运行时文件夹结构中的所有资产,以便在运行时在多个环境中工作。我怎样才能做到这一点?

编辑:

我最终为本地库绑定创建了一个 nuget 包,并在我的其他项目中引用了 nuget。

And*_*zym 6

这应该将您的文件夹结构复制到输出文件夹,只需将其立即</PropertyGroup>放在您的第一个文件夹下MyApp.csproj

<ItemGroup>
    <None Update="runtimes\**" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

以防万一,有一种方法可以更好地控制如何DllImport通过DllImportResolver委托为程序集加载本机库。

public delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);
Run Code Online (Sandbox Code Playgroud)

还有一个NativeLibrary类允许为 .net 核心设置和加载本机库。一些示例代码:

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();
}
Run Code Online (Sandbox Code Playgroud)