我正在使用PowerShell Core编写P/Invoke代码,但失败了.

using System;
using System.Runtime.InteropServices;

public class Bindings
{
    [DllImport("MyEncoder.dll")]
    public static extern bool EncodeStream(
        byte[] pbIn,
        int cbIn,
        ref byte pbOut,
        out int cbOut);
}

C#代码如下:

var pbOut = new byte[pbIn.Length];
int cbOut = 0;
Bindings.EncodeStream(pbIn, pbIn.Length, ref pbOut[0], out cbOut);

它起作用了.

我的PowerShell代码是:

$Bindings = Add-Type -TypeDefinition $cs_code -PassThru

[byte[]]$pbIn = [IO.File]::ReadAllBytes("src.txt")
$cbIn = $pbIn.Length

$pbOut = [byte[]]::new($cbIn)
$cbOut = [int]0

# PowerShell 7.3.9
# Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
$Bindings::EncodeStream($pbIn, $cbIn, [ref]$pbOut[0], [ref]$cbOut)

我试着调试,发现$pbOut $pbOut[0]返回了GCHandle.AddrOfPinnedObject个不同的地址.所以我想知道是不是$pbOut[0]创建了新值,而PoewrShell引用了临时值.

任何帮助和测试都欢迎!

推荐答案

PowerShell的[ref] type和C#的S ref keyword的功能非常不同,您从根本上无法获得对PowerShell中单个数组元素的引用.

要解决此限制,请围绕您的P/Invoke方法创建一个C#wrapper方法,该方法:

  • 接受来自PowerShell的整个byte[]数组,并在P/Invoke调用中使用ref pbOut[0] internally.
  • for easier use from PowerShell:
    • returns值为cbOut
    • 如果发生错误,则抛出exception.

以下内容(未经测试):

$Bindings = Add-Type -PassThru @'
using System;
using System.Runtime.InteropServices;

public class Bindings
{
    public static int EncodeStream(byte[] pbIn, byte[] pbOut)
    {
      int cbOut;
      if (!EncodeStream_Impl(pbIn, pbIn.Length, ref pbOut[0], out cbOut)) 
      {
        throw new Exception("Encoding failed.");
      }
      return cbOut;
    }

    [DllImport("MyEncoder.dll", EntryPoint="EncodeStream")]
    private static extern bool EncodeStream_Impl(
        byte[] pbIn,
        int cbIn,
        ref byte pbOut,
        out int cbOut);
}
'@

[byte[]]$pbIn = [IO.File]::ReadAllBytes("src.txt")

$pbOut = [byte[]]::new($pbIn.Length)

$cbOut = $Bindings::EncodeStream($pbIn, $pbOut)

Csharp相关问答推荐

我应该将新的httpReportMessage()包装在using声明中吗?

如何在C#中删除一个特殊字符,如"使用Regex"

try 还原包时出错:Dapper已经为System.Data.SQLClient定义了依赖项''''

如何使用ConcurentDictionary属性上的属性将自定义System.Text.Json JsonConverter应用于该属性的值?

具有单一导航属性的EF核心一对多关系

为什么SignalR在每个Blazor服务器应用程序启动时最多启动8个服务器?

.NET 6控制台应用程序,RabbitMQ消费不工作时,它的程序文件中的S

MigraDoc文档

如何在C#中实现非抛出`MinBy`?

在IAsyncEnumerable上先调用,然后跳过(1)可以吗?

将类移动到新命名空间后更新RavenDB Raven-Clr-Type

如何在onNext之前等待订阅者完成?

RX操作员使用先前值进行扫描,信号来自值本身

{ or ; expected error如何解决此问题

VS代码扩展无法在新版本扩展C#中运行从v2.10.28开始

C#Microsoft.CodeAnalysis.CSharp.Scriiting不等待并行.对于

如何在C#控制台应用程序中获取用户输入并将其作为订单项目进行处理?

外部应用&&的LINQ;左外部连接&类似于PostgreSQL的查询

这是T自身的布尔表达式是什么意思?

带有类约束的C#泛型