c# - 使用没有 Assembly.Load 或类似的 P/invoke 调用托管 C# 库
问题描述
我已经找了好几天了,但我发现的只是如何使用 P/Invoke 从 C# 调用非托管库。我需要以不同的方式做:我希望使用 P/Invoke 从另一个调用托管程序集(或使用其他东西,避免调用Assembly.Load
,Assembly.LoadFrom
等),主要是由于 CoreRT/NativeAOT 限制(参见此处) .
基本上,使用 CoreRT/NativeAOT 的想法是由于原生可执行文件的生成,这将提高我的应用程序的安全性,因为常见的反编译器无法使用它(除了 IDA 和具有 ASM 知识的聪明开发人员,但他们更难过来)。考虑到 CoreRT/NativeAOT 不能(它可以,但 .NET 团队现在不想......)使用任何 .NET 互操作方法(Assembly.Load
、Assembly.LoadFrom
等)加载外部程序集,但它可以使用DllImport
,我'想调用一个外部程序集,如果不使用任何这些程序集加载方法,它是否被反编译,我并不在意。
是的,我知道我可以用 CoreRT 本身编写一个包装器或其他东西来生成一个本机库,并从应用程序中使用 P/Invoke 调用它,但是对于由于 而无法编译的实体框架Reflection.Emit
,这是不可能的。
这里的理想解决方案是知道如何在不使用 Assembly.Load/LoadFrom/LoadFromStream/etc 的情况下从另一个 C# 应用程序/程序集调用任何 .NET 程序集 (DLL)。使用其他方法,可以是 P/Invoke(可以吗?)或其他方法。
解决方案
解决方案
感谢@ChristianHeld 建议使用 .NET 5.0 的 Native Exports(还要感谢 Aaron Robinson 的代码。我是这样工作的:
.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
ADD THIS -> <EnableDynamicLoading>true</EnableDynamicLoading>
ADD THIS -> <DnneAddGeneratedBinaryToProject>true</DnneAddGeneratedBinaryToProject>
</PropertyGroup>
<ItemGroup>
ADD THIS -> <PackageReference Include="DNNE" Version="1.*" />
</ItemGroup>
</Project>
库 .NET 代码(剥离):
[UnmanagedCallersOnlyAttribute]
public static void Init()
{
// ... Some code here...
}
调用方 .NET 代码(示例):
class Program
{
const string LIBNAME = @"LibraryNE.dll";
[DllImport(LIBNAME)] public static extern void Init();
static void Main(string[] args)
{
Init();
}
}
重要提示:使用 VSCode (F5) 运行时,它可能会这样说:
Failed to initialize context for config: C:\Project\Library.runtimeconfig.json. Error code: 0x80008092
忽略这一点,因为它似乎发生了,因为 VSCode 使用 调试应用程序dotnet.exe
,忽略每个程序集的 runtimeconfig.json (不知何故它抛出LibHostInvalidArgs
。不知道为什么)。
如果您直接执行应用程序的 .EXE,它将起作用(只需将其与 CoreRT/NativeAOT 生成的二进制文件一起使用)。对此的解决方案是编辑您的launch.json
文件并.dll
使用.exe
in 进行更改configurations -> program
。
另外,请记住也要复制 .NET dll。好像发布的时候只复制原生库(以NE为后缀),但它本身并不能工作,因为它只是一个包装器。它也需要真正的 .NET dll 位于同一文件夹中。
调试体验不是很好,因为当您调试该方法时,它似乎使用不同的、不存在的源文件,因此单步执行时的行号不匹配。它是可调试的,但您将针对幽灵/偏移线这样做。
推荐阅读
- google-analytics - Google Analytics realtime 在 7 分钟后显示不准确的来源
- java - 带有 ImageIcon 的 Java 构造函数
- php - 为什么在 php 脚本中使用“使用函数”?
- php - 这是计算唯一身份访问者的好方法吗?
- ios - 如何为登录屏幕ios swift编写测试用例?
- c++ - 使用 Clang 编译 DLL 时指定 DEF 文件
- discord - 前缀正在改变
- visual-studio-2019 - Visual Studio 2019:任务列表中仅显示 TODO 标记
- visual-studio-code - 如何在 package.json 中禁用“调试”
- python - 如何在numpy中将一个数组除以另一个数组元素?