You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用.NET Core CLI打包包含非托管DLL的NuPkg包?

嘿,这个问题我熟——把带非托管DLL依赖的.NET Core类库打包成能正常工作的NuGet包,核心就是得让NuGet把那些非托管文件送到引用项目的正确位置,确保运行时能找得到。下面是一步步的实操方案:

核心逻辑先理清

非托管DLL没法像托管程序集那样直接被项目引用,所以咱们得借助NuGet的打包规则,把这些平台特定的文件打包进NuPkg,并且让引用项目在构建/运行时能自动找到它们。最稳妥的方式是遵循NuGet的运行时特定文件结构,或者用MSBuild目标文件自定义复制逻辑。

1. .csproj文件的关键配置

首先,先给你的非托管DLL建个标准的目录结构,放在类库项目根目录下:

你的类库项目/
├── runtimes/
│   ├── win-x86/
│   │   └── native/
│   │       └── YourNativeLib.dll
│   ├── win-x64/
│   │   └── native/
│   │       └── YourNativeLib.dll
│   └── linux-x64/
│       └── native/
│           └── libYourNativeLib.so
└── YourLibrary.csproj

这个结构是NuGet官方认可的,会自动根据目标项目的运行时标识(RID)匹配对应的非托管文件。

接下来修改YourLibrary.csproj,添加以下配置:

配置1:包含非托管文件到NuGet包

<ItemGroup>
  <!-- 递归包含runtimes目录下的所有非托管文件,打包时保留原目录结构 -->
  <None Include="runtimes/**/*" Pack="true" PackagePath="%(RecursiveDir)" />
</ItemGroup>

配置2:指定支持的运行时标识

<PropertyGroup>
  <!-- 列出你要支持的所有平台RID,按需调整 -->
  <RuntimeIdentifiers>win-x86;win-x64;linux-x64</RuntimeIdentifiers>
  <!-- 让.NET自动处理非托管库的提取(针对.NET Core 3.0+) -->
  <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>

配置3:DllImport的正确写法

确保你的DllImport只写文件名,不用带路径——.NET会自动在匹配的runtimes/{RID}/native目录下查找:

// Windows下的写法
[DllImport("YourNativeLib.dll")]
private static extern void YourNativeMethod();

// Linux下的写法(注意lib前缀)
[DllImport("libYourNativeLib.so")]
private static extern void YourNativeMethod();

如果要跨平台兼容,可以用条件编译区分。

2. 可选:用.targets文件自定义复制逻辑

如果官方的runtimes结构满足不了你的需求(比如你想把非托管DLL直接复制到输出目录根目录),可以添加一个MSBuild目标文件来控制复制行为:

  1. 在类库项目根目录创建YourLibrary.targets文件,内容如下:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <!-- 匹配当前运行时对应的非托管DLL -->
    <NativeLibs Include="$(MSBuildThisFileDirectory)..\runtimes\$(RuntimeIdentifier)\native\*" />
  </ItemGroup>
  <Target Name="CopyNativeDependencies" BeforeTargets="Build">
    <!-- 把非托管DLL复制到项目输出目录 -->
    <Copy SourceFiles="@(NativeLibs)" DestinationFolder="$(OutputPath)" />
  </Target>
</Project>
  1. 在YourLibrary.csproj里把这个.targets文件打包到NuGet的build目录:
<ItemGroup>
  <None Include="YourLibrary.targets" Pack="true" PackagePath="build\$(TargetFramework)" />
</ItemGroup>

这样引用这个NuGet包的项目在构建时,会自动执行这个目标,把对应平台的非托管DLL复制到输出目录。

3. 打包与测试

用.NET CLI执行打包命令:

dotnet pack -c Release

生成的NuPkg会在bin/Release目录下。你可以把它添加到本地NuGet源,然后新建一个测试项目引用这个包,运行后检查输出目录是否有对应的非托管DLL,同时验证原生方法是否能正常调用。

避坑提醒
  • 平台一致性:不同架构的非托管DLL不能混用,一定要按RID分开存放,否则会出现DllNotFoundException。
  • 文件名匹配:DllImport的文件名必须和非托管文件完全一致,Linux下的SO文件通常带lib前缀,别漏了。
  • .NET Framework兼容:如果要支持.NET Framework项目,可能需要额外配置PackagePath为build/net4xx,但.NET Core/.NET 5+的标准结构基本能兼容大部分场景。

内容的提问来源于stack exchange,提问作者UlfW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:34:02