网站首页 > 技术文章 正文
起因
在看.Net源码时候,发现调用Native库的新方式,这种方式是在.Net 5的时候加入的.下面我们一起看看新的调用方式.这种方式适合调用一次调用调用多个函数.
新方式是在System.Runtime.InteropServices加入NativeLibrary这个静态工具类.主要有这几个函数可以调用.
- Load/TryLoad 加载动态库(dll/so文件)
- GetExport/TryGetExport 根据函数名获取函数地址/句柄
- Free 释放动态库
- SetDllImportResolver 设置回调函数
如何使用
//1. 加载动态库 Load有函数重载,可以指定动态库的路径,这里只是为了省事
IntPtr dllPtr = NativeLibrary.Load("E:/project/csharp/Dotnet6App/net6perf/b.dll");
//2. 根据函数名称获取动态库加载到内存中的函数地址
delegate* unmanaged[Cdecl]<int, int, int> addFuncPointer =
(delegate* unmanaged[Cdecl]<int, int, int>)NativeLibrary.GetExport(dllPtr, "add");
int sum = 0;
for (int i = 0; i < 100; i++)
{
sum += addFuncPointer(1, 0);
}
Console.WriteLine(sum);
//3. 不使用的时候,对动态库进行释放
if (dllPtr != IntPtr.Zero)
{
NativeLibrary.Free(dllPtr);
}
看.Net 源码中是如何使用NativeLibrary
Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
//使用unsafe和sealed(密封类)标记
internal unsafe sealed class MsQuicApi
{
private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000);
public SafeMsQuicRegistrationHandle Registration { get; }
//私有构造函数,在静态构造函数中进行实列化
private MsQuicApi(NativeApi* vtable)
{
uint status;
//一次性将返回函数进行委托,在需要的时候调用
SetParamDelegate =
Marshal.GetDelegateForFunctionPointer<SetParamDelegate>(
vtable->SetParam);
GetParamDelegate =
Marshal.GetDelegateForFunctionPointer<GetParamDelegate>(
vtable->GetParam);
//移除部分函数
var cfg = new RegistrationConfig
{
AppName = ".NET",
ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
};
status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle);
QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed.");
Registration = handle;
}
internal static MsQuicApi Api { get; } = null!;
internal static bool IsQuicSupported { get; }
private const int MsQuicVersion = 1;
//使用静态构造函数
static MsQuicApi()
{
if (OperatingSystem.IsWindows() && !IsWindowsVersionSupported())
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(null, #34;Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}");
}
return;
}
//在.Net 5开始支持Http3,是通过调用微软的另外一个开源msquic实现.
//加载msquic.dll,返回dll在内存中的句柄
if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle))
{
try
{
//获取MsQuicOpenVersion的在内存中的调用地址
if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
{
//将MsQuicOpenVersion函数的入口地址转为函数指针
delegate* unmanaged[Cdecl]<uint, out NativeApi*, uint> msQuicOpenVersion =
(delegate* unmanaged[Cdecl]<uint, out NativeApi*, uint>)msQuicOpenVersionAddress;
//传入版本号(目前是1),返回一个NatvieApi结构体类型的指针
uint status = msQuicOpenVersion(MsQuicVersion, out NativeApi* vtable);
if (MsQuicStatusHelper.SuccessfulStatusCode(status))
{
IsQuicSupported = true;
//将函数列表传入私有的构造函数
Api = new MsQuicApi(vtable);
}
}
}
finally
{
//如果不支持,将msquic.dll进行释放
if (!IsQuicSupported)
{
NativeLibrary.Free(msQuicHandle);
}
}
}
}
private static bool IsWindowsVersionSupported() => OperatingSystem.IsWindowsVersionAtLeast(MinWindowsVersion.Major,
MinWindowsVersion.Minor, MinWindowsVersion.Build, MinWindowsVersion.Revision);
//移除部分代码
internal SetParamDelegate SetParamDelegate { get; }
internal GetParamDelegate GetParamDelegate { get; }
}
}
如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流
- 上一篇: jQuery如何实现下拉菜单
- 下一篇: HBase简介
猜你喜欢
- 2025-01-04 一次“败笔”之后,微信会否遭遇QQ的困境?
- 2025-01-04 鸿蒙ArkUI-X已更新适配API13啦
- 2025-01-04 微软详解.Net Native:Win10通用应用性能的保障
- 2025-01-04 Hibernate 和 JPA
- 2025-01-04 开发不同类型的App需要用到哪些技术?
- 2025-01-04 迅雷极速版v1.0.12 下载:批量下载磁力链接
- 2025-01-04 DevExpress v16.1新功能介绍
- 2025-01-04 Android native开发环境搭建
- 2025-01-04 基于C++音视频高手课-WebRTC远程桌面后台服务实战
- 2025-01-04 Electron简介
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)