PowerShell调用DLL时如何传入绑定本地函数的函数指针
实现方案
你的思路完全可行,不需要调整方向,.NET 运行时会自动将标注了互操作特性的委托转换为C侧可识别的函数指针,无需额外编写C风格封装代码,完整实现步骤如下:
步骤1:加载互操作类型定义
将委托定义和DLL导出函数的P/Invoke声明合并后,通过Add-Type编译到当前PowerShell会话中:
$typeDefinition = @' using System.Runtime.InteropServices; // 你已经定义好的互操作委托 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void CallbackDelegate([MarshalAs(UnmanagedType.LPTStr)] string entry); // 声明DLL的Finalize导出函数 public static class MyDllWrapper { // 替换为你实际的DLL路径,建议使用绝对路径避免加载失败 [DllImport("your_dll_name.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void Finalize(CallbackDelegate writeEntry); } '@ Add-Type -TypeDefinition $typeDefinition
步骤2:构造委托并调用DLL方法
将PowerShell侧的WriteEntry函数包装为CallbackDelegate委托实例后直接传入即可:
# 你已经定义好的PowerShell侧日志函数 function WriteEntry { param([string]$entry) # 自定义处理逻辑示例 Write-Host "收到DLL回调内容:$entry" } # 构造互操作委托实例 $callback = [CallbackDelegate]::new({ param([string]$entry) WriteEntry $entry }) # 调用DLL的Finalize方法 [MyDllWrapper]::Finalize($callback)
关键注意事项
- 委托实例的生命周期必须覆盖DLL使用回调的全周期:如果DLL的
Finalize是异步执行、或者后续还会持续调用该回调,必须将$callback变量存储在不会被垃圾回收的作用域(比如全局作用域$global:callback = $callback),或在回调不再使用前调用[GC]::KeepAlive($callback)防止委托被回收导致DLL调用空指针崩溃。 - 如果C侧
const char*使用UTF8编码,将委托参数的MarshalAs参数改为[MarshalAs(UnmanagedType.LPUTF8Str)]可避免中文乱码问题。
内容的提问来源于stack exchange,提问作者brandon_busby
相关产品推荐
相关产品推荐

