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

如何遵循NuGet包runtimes文件夹规范正确选择动态库?

解决NuGet包中跨平台动态库的DllImport路径问题

问题背景

你正在构建包含动态库绑定的NuGet包,各平台共享库(.so/.dylib/.dll)存放在runtimes文件夹,项目打包配置如下:

<ItemGroup>
  <None Include="runtimes/win-x64/native/*" PackagePath="runtimes/win-x64/native/" Pack="true" />
  <None Include="runtimes/linux-x64/native/*" PackagePath="runtimes/linux-x64/native/" Pack="true" />
  <!-- 其他平台配置 -->
</ItemGroup>

此前硬编码路径的DllImport仅能在linux-x64生效:

let UtilsLibPath = "runtimes/linux-x64/native/libutils.so"

[<DllImport(UtilsLibPath, CallingConvention = CallingConvention.Cdecl)>]
extern int foo()

核心原理

NuGet在安装包时,会根据目标平台自动将runtimes/{RID}/native下的库提取到项目输出目录,因此无需硬编码完整路径,只需指定库文件名即可让.NET运行时自动探测加载。

解决方案

方案1:条件编译指定平台专属库名

利用F#的条件编译指令,针对不同平台定义对应的库名,配合项目文件的编译符号实现跨平台兼容:

1.1 编写带条件编译的绑定代码

#if WINDOWS
let private UtilsLibName = "utils.dll"
#elif LINUX
let private UtilsLibName = "libutils.so"
#elif OSX
let private UtilsLibName = "libutils.dylib"
#endif

[<DllImport(UtilsLibName, CallingConvention = CallingConvention.Cdecl)>]
extern int foo()

1.2 在项目文件中添加平台编译符号

<PropertyGroup>
  <DefineConstants Condition="'$(RuntimeIdentifier)' == 'win-x64'">WINDOWS;$(DefineConstants)</DefineConstants>
  <DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-x64'">LINUX;$(DefineConstants)</DefineConstants>
  <DefineConstants Condition="'$(RuntimeIdentifier)' == 'osx-x64'">OSX;$(DefineConstants)</DefineConstants>
  <!-- 按需添加其他平台的RuntimeIdentifier -->
</PropertyGroup>

方案2:运行时动态加载(无编译条件依赖)

通过RuntimeInformation判断当前平台,动态加载对应库并获取函数指针:

open System.Runtime.InteropServices

let private getUtilsLibName () =
    match RuntimeInformation.OSPlatform with
    | OSPlatform.Windows -> "utils.dll"
    | OSPlatform.Linux -> "libutils.so"
    | OSPlatform.OSX -> "libutils.dylib"
    | _ -> failwith "Unsupported operating system"

// 动态加载库并绑定函数
let utilsLibHandle = NativeLibrary.Load(getUtilsLibName())
let foo = Marshal.GetDelegateForFunctionPointer<int>(NativeLibrary.GetExport(utilsLibHandle, "foo"))

// 调用示例
let result = foo()

优化NuGet打包配置

将原有的逐个平台配置简化为递归匹配,减少重复代码:

<ItemGroup>
  <None Include="runtimes/**/native/*"
        PackagePath="runtimes/%(RecursiveDir)"
        Pack="true"
        CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:14:59