我有一个以前用 .NET Framework 编写的应用程序。 Robert Giesecke UnmanagedExport 非常适合将
[DllExport]
属性添加到我的函数中,以将它们公开给本机语言。
现在我们已经升级到.Net6.0了,这似乎不起作用了。这些函数可导出并使用
dumpbin
可见。它们确实以本地语言加载,并且可以找到函数地址。虽然,在执行该函数时,我遇到了异常Unhandled exception at 0x00007FFB928CCD29 (KernelBase.dll) in NativeExportTest.exe: 0xE0434352
如果我切换回 .NET Framework 或 .NET Standard,一切都会恢复正常。我已经尝试过以下软件包;
我还查看了 .NET6.0 的
[UnmanagedCallersOnlyAttribute]
,但底层的本机语言很奇怪,在运行时被编译成 C++。我不相信它支持回调。
有没有办法将 .NET6.0 c# 函数导出到本地语言而不依赖回调?
我只需要 Windows 的解决方案。
C#
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="UnmanagedExports.Repack.Upgrade" Version="1.2.1" />
</ItemGroup>
</Project>
public class Class1
{
[DllExport]
public static int _add(int a, int b)
{
return a + b;
}
}
一些 C++ 适用于 .NET Framework,但不适用于 .NET Core。
const TCHAR* pemodule = _T("path to release dll");
HMODULE lib = LoadLibrary(pemodule);
typedef int( *_add)(int a, int b);
auto pAdd = (_add)GetProcAddress(lib, "_add");
int c = pAdd(1,2); // Exception here
按照 Hans Passants 启用混合调试的建议,我遇到了一个新的异常。现在,在加载任何代码之前,异常会显示在控制台中:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
我通过升级到 .NET 7.0 并使用内置导出功能
[UnmanagedCallersOnly]
而不是 [DllExport]
来实现此功能。可以从 C++ 调用函数并按预期显示在 dumpbin 中。
请注意,项目必须发布为
PublishAot
、Shared
和 SelfContained
。
dotnet publish -f net7.0 -c Release -r win-x64 -p:PublishAot=true -p:NativeLib=Shared -p:SelfContained=true
不幸的是,这看起来仍然只是 x64 的解决方案。我正在连接到在 x64 Windows 上作为 x86 运行的旧应用程序。为此,我创建了 .NET Framework x86
DllExport
,它使用 API 调用充当 .NET Core 的层。希望未来能有更好的 NativeAOT 支持。