来自 NuGet 包的 DllImport 本机依赖项不适用于 net472,但适用于 netcoreapp2.2

Pau*_*opf 6 .net pinvoke nuget

我的项目目前在 .NET Core (Linux/OSX/Windows/ netcoreapp2.2)上完美运行。它也应该工作net472,但由于某种原因,DllImport没有找到本机依赖项。

可以在此处找到一个简单的重现,但我将在此问题中进一步扩展以供后代使用。

这是包含本机依赖项的打包项目。

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="../../build/common.props" />
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
    <EnableDefaultItems>false</EnableDefaultItems>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <IncludeBuildOutput>false</IncludeBuildOutput>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\net\Qml.Net\Qml.Net.csproj" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="output/**/*">
      <PackagePath>runtimes/win-x64/native/</PackagePath>
      <Pack>true</Pack>
    </Content>
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

这将生成具有以下输出的 NuGet 包。

??? [Content_Types].xml
??? package
?   ??? services
?       ??? metadata
?           ??? core-properties
?               ??? e803485f4a674e8d9d0155224fa9cbc2.psmdcp
??? Qml.Net.WindowsBinaries.nuspec
??? _rels
??? runtimes
    ??? win-x64
        ??? native
            ??? QmlNet.dll

8 directories, 4 files
Run Code Online (Sandbox Code Playgroud)

这是我的消费项目。

??? [Content_Types].xml
??? package
?   ??? services
?       ??? metadata
?           ??? core-properties
?               ??? e803485f4a674e8d9d0155224fa9cbc2.psmdcp
??? Qml.Net.WindowsBinaries.nuspec
??? _rels
??? runtimes
    ??? win-x64
        ??? native
            ??? QmlNet.dll

8 directories, 4 files
Run Code Online (Sandbox Code Playgroud)

这是尝试执行 PInvoke 的简单代码。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
    <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
  </PropertyGroup>
  <ItemGroup>
    <None Remove="**\*.qmlc" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Qml.Net" Version="0.9.0-alpha.5" />
    <PackageReference Include="Qml.Net.WindowsBinaries" Version="0.9.0-alpha.5" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="images\**" CopyToPublishDirectory="Always" />
    <Content Include="pages\**" CopyToPublishDirectory="Always" />
    <Content Include="Main.qml" CopyToPublishDirectory="Always" />
  </ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

当我运行这个时,我得到:

System.DllNotFoundException: 'Unable to load DLL 'QmlNet': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'
Run Code Online (Sandbox Code Playgroud)

我尝试net472在我的 NuGet 包中添加一个显式目标,但没有用。

当我的消费项目目标时,我没有收到任何错误netcoreapp2.2

DllImport在定位时如何让我的本机依赖项被发现net472

Lan*_*aas 0

这个答案帮助我从 nuget 包中加载本机文件。我唯一做的额外事情就是像这样使用当前目录

private static IntPtr ImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
    IntPtr libHandle = IntPtr.Zero;
    //TODO: Add check for windows if needed.
    if (libraryName == WrapperFFI && RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && Environment.Is64BitOperatingSystem)
    {
        var res = NativeLibrary.TryLoad(System.IO.Directory.GetCurrentDirectory()+"/bin/Debug/netcoreapp3.1/runtimes/linux-x64/native/libwrapper_ffi.so", out libHandle);
        if (!res) {
            res = NativeLibrary.TryLoad(System.IO.Directory.GetCurrentDirectory()+"/bin/Release/netcoreapp3.1/runtimes/linux-x64/native/libwrapper_ffi.so", out libHandle);
        }
    } 
    return libHandle;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

尽管上述修复对大多数人来说都有效,但当我提取在私人存储库上构建的 nuget 包时,它却不起作用。私有仓库的本机库是在 centos 上构建的,这会产生较小的二进制文件,但我仍然无法在我的 ubuntu 开发机器上加载异常。ldd 显示的 centos 库比 ubuntu 上构建的库具有更多依赖项

乌班图:

在此输入图像描述

森托斯:

在此输入图像描述

所以我将创建一个 ubuntu 构建书来快速解决这个问题