You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:30:01