My project currently works flawlessly on .NET Core (Linux/OSX/Windows/netcoreapp2.2
). It should work on net472
as well, but for some reason, DllImport
isn't finding the native dependency.
A simple repro can be found here, but I will expand further in this question for posterity.
Here is the project that is packed that contains the native dependency.
<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>
This will produce a NuGet package with the following output.
├── [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
Here is my consuming project.
<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>
And here is the simple code that is trying to do the PInvoke.
using System;
using System.Runtime.InteropServices;
using Qml.Net.Runtimes;
namespace Features
{
class Program
{
// NOTE: This works if I provide absolute path to QmlNet.dll
[DllImport("QmlNet")]
internal static extern long qml_net_getVersion();
static int Main(string[] args)
{
// This is need to prep Qt runtime that QmlNet.dll depends on.
// It is required, but it is irrelvant to the issue we are experiencing.
RuntimeManager.DiscoverOrDownloadSuitableQtRuntime();
// The following works on netcoreapp2.2, but not on 4.7.2.
Console.WriteLine(qml_net_getVersion());
return 0;
}
}
}
When I run this, I get:
System.DllNotFoundException: 'Unable to load DLL 'QmlNet': The specified module could not be found. (Exception from HRESULT: 0x8007007E)'
I tried adding an explicit target to net472
in my NuGet package, didn't work.
I don't get any errors when my consuming project targets netcoreapp2.2
.
How do I get my native dependency to be property discovered with DllImport
when targeting net472
?
This answer helped me get my native file loaded from my nuget package. The only thing I did extra was use the current directory like this
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;
}
Edit:
Even though the above fix will work for most it did not work when I pulled my nuget package built on a private repo. The private repo's native lib gets built on centos which results in a smaller binary, but I still get unable to load exception on my ubuntu dev machine. The centos lib had more dependencies shown by ldd than the one built on ubuntu
Ubuntu:
Centos:
So I will just create an ubuntu build boks to quickly get around the issue
User contributions licensed under CC BY-SA 3.0