You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将C++ DLL复制到引用它们的任意C#项目构建输出目录?

解决C++/CLI依赖的原生DLL自动复制与NuGet打包问题

我之前也碰到过一模一样的场景——C#类库套着C++/CLI层,底下还有一堆原生C++ DLL,默认构建时根本不会把这些原生DLL带到最终应用的输出目录,做NuGet包的时候更是头疼。给你几个靠谱的解决方案:

方案1:修改C++/CLI项目配置,强制同步原生DLL

这是最直接的办法,不用碰上层C#项目或者NuGet配置:

  • 打开你的C++/CLI项目属性,找到链接器 -> 常规,确认“附加库目录”已经包含原生C++ DLL的输出路径
  • 切换到生成事件 -> 后期生成事件,添加命令行复制原生DLL到CLI项目的输出目录:
    xcopy /Y "$(SolutionDir)Path\To\Your\NativeDlls\$(PlatformTarget)\*.dll" "$(TargetDir)"
    
    这样每次CLI项目编译完成,都会把依赖的原生DLL同步到自己的输出目录,之后C#类库引用CLI项目时,就会自动把CLI DLL和附带的原生DLL一起复制到上层应用的输出目录。

方案2:通过NuGet的.targets文件自动处理依赖

如果要把C#类库做成NuGet包,这个是最佳实践,能让任何安装包的项目自动获取所有依赖:

  1. 在C#类库项目中新建build文件夹(名字必须是build,NuGet会自动识别)
  2. build里创建一个和NuGet包同名的.targets文件,比如YourLibrary.targets,内容如下:
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <ItemGroup>
        <NativeDlls Include="$(MSBuildThisFileDirectory)..\runtimes\win-$(Platform)\native\*.dll" />
      </ItemGroup>
      <Target Name="CopyNativeDlls" AfterTargets="Build">
        <Copy SourceFiles="@(NativeDlls)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true" />
      </Target>
    </Project>
    
  3. 按平台整理原生DLL,放到runtimes\win-x64\nativeruntimes\win-x86\native这类符合NuGet runtime约定的目录下
  4. 修改.nuspec文件(或者通过项目文件的PackageReference配置),把buildruntimes文件夹都包含进NuGet包:
    <files>
      <file src="bin\$(Configuration)\net6.0\YourLibrary.dll" target="lib\net6.0" />
      <file src="build\**" target="build" />
      <file src="runtimes\**" target="runtimes" />
    </files>
    
    用户安装你的NuGet包后,MSBuild会自动执行.targets里的复制命令,把对应平台的原生DLL放到应用输出目录,完全不用用户手动配置。

方案3:让原生C++项目直接输出到CLI目录

如果原生C++项目和CLI项目在同一个解决方案里,可以直接修改原生项目的输出路径:

  • 打开原生C++项目属性,找到常规 -> 输出目录,设置为$(SolutionDir)YourCLIProject\$(Configuration)\$(PlatformTarget)\
  • 这样原生项目编译后,DLL直接输出到CLI项目的目录里,CLI项目会把这些DLL当成自己的输出文件,上层C#项目引用CLI时就会自动复制过去。
    这个方案适合团队内部项目,减少复制步骤,但如果原生DLL是第三方的就不太适用。

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

火山引擎 最新活动