具有本机库依赖项的 .NET Core 项目
.NET Core project with native library depedency
我正在使用 [DllImport]
在 .NET Core 中编写一个依赖本机代码的应用程序。我有 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
当我 运行 应用程序时,我发现 DLL 未找到异常。
我曾尝试使用 MSBuild 目标解决方案 ,但这只会在编译时将一个 dll
复制到主输出文件夹。但是,我希望输出以与上面 运行times 文件夹相同的结构在输出文件夹中包含所有三个本机库,并将兼容本机库的选择留给 .NET Core 运行时间主持.
因此,如果用户 运行 在 Windows x86 中使用应用程序,它将使用 win-x86,依此类推。
我注意到,当我从 NuGet 中引用 SkiaSharp 等原生包装器时,它实际上会很好地集成到我的应用程序中,并将所有资产包含在 运行 次文件夹结构中以处理多个运行 时间的环境。我该怎么做?
编辑:
我最终为本机库绑定创建了一个 nuget 包,并在我的其他项目中引用了该 nuget。
由于您没有提供任何代码片段来显示您对 DllImportAttribute
的使用或您的应用程序可能执行的任何其他环境初始化,因此很难猜测究竟是什么地方出了问题.
根据现有信息,最有可能的罪魁祸首只是 P/Invoke 系统不知道如何找到您的本机库。您的代码库是否有某种机制可以将搜索路径添加到运行时?或者您是否有机会使用 custom load context?
这应该将您的文件夹结构复制到输出文件夹,只需将其立即放在 MyApp.csproj
中的第一个 </PropertyGroup>
下即可:
<ItemGroup>
<None Update="runtimes\**" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
以防万一,有一种方法可以通过 DllImportResolver
委托为程序集使用 DllImport
来更好地控制如何加载本机库。
public delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);
还有 NativeLibrary
class 允许为 .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();
}
我正在使用 [DllImport]
在 .NET Core 中编写一个依赖本机代码的应用程序。我有 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
当我 运行 应用程序时,我发现 DLL 未找到异常。
我曾尝试使用 MSBuild 目标解决方案 dll
复制到主输出文件夹。但是,我希望输出以与上面 运行times 文件夹相同的结构在输出文件夹中包含所有三个本机库,并将兼容本机库的选择留给 .NET Core 运行时间主持.
因此,如果用户 运行 在 Windows x86 中使用应用程序,它将使用 win-x86,依此类推。
我注意到,当我从 NuGet 中引用 SkiaSharp 等原生包装器时,它实际上会很好地集成到我的应用程序中,并将所有资产包含在 运行 次文件夹结构中以处理多个运行 时间的环境。我该怎么做?
编辑:
我最终为本机库绑定创建了一个 nuget 包,并在我的其他项目中引用了该 nuget。
由于您没有提供任何代码片段来显示您对 DllImportAttribute
的使用或您的应用程序可能执行的任何其他环境初始化,因此很难猜测究竟是什么地方出了问题.
根据现有信息,最有可能的罪魁祸首只是 P/Invoke 系统不知道如何找到您的本机库。您的代码库是否有某种机制可以将搜索路径添加到运行时?或者您是否有机会使用 custom load context?
这应该将您的文件夹结构复制到输出文件夹,只需将其立即放在 MyApp.csproj
中的第一个 </PropertyGroup>
下即可:
<ItemGroup>
<None Update="runtimes\**" CopyToOutputDirectory="PreserveNewest"/>
</ItemGroup>
以防万一,有一种方法可以通过 DllImportResolver
委托为程序集使用 DllImport
来更好地控制如何加载本机库。
public delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);
还有 NativeLibrary
class 允许为 .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();
}