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

如何在PowerShell中创建含普通数组的非托管结构体并正确赋值?

PowerShell处理C风格结构体数组字段及序列化方案

问题根源

  1. 数组未初始化:.NET结构体中的引用类型(如数组)默认初始化为null,直接索引赋值会抛出"Cannot index into a null array"错误。
  2. 类型不匹配:原代码中Int16/Int32与C结构体的uint16_t类型不对应,会导致内存布局偏差,必须改用UInt16匹配无符号16位整数。

修复数组初始化问题

先为thresholds数组分配指定大小的实例,再进行元素赋值:

$typeCode = @'
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[Serializable]
public struct MyConfig
{
    public UInt16 level; // 匹配C的uint16_t
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public UInt16[] thresholds; // 匹配C的uint16_t[16]
}
'@

Add-Type -TypeDefinition $typeCode

$config = New-Object MyConfig
$config.level = 1

# 先初始化数组
$config.thresholds = New-Object UInt16[] 16
# 逐个赋值
$config.thresholds[0] = 1
$config.thresholds[1] = 2
# ... 其他元素按需赋值

将结构体序列化为二进制Blob并写入文件

使用System.Runtime.InteropServices.Marshal类完成结构体到字节数组的转换,再写入文件:

# 计算结构体大小
$structSize = [System.Runtime.InteropServices.Marshal]::SizeOf($config)
# 分配非托管内存
$ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($structSize)
try {
    # 将结构体拷贝到非托管内存
    [System.Runtime.InteropServices.Marshal]::StructureToPtr($config, $ptr, $false)
    # 从非托管内存读取字节数组
    $byteArray = New-Object byte[] $structSize
    [System.Runtime.InteropServices.Marshal]::Copy($ptr, $byteArray, 0, $structSize)
    # 写入文件
    [System.IO.File]::WriteAllBytes("MyConfig.bin", $byteArray)
}
finally {
    # 释放非托管内存,避免泄漏
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
}

完整示例代码

$typeCode = @'
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
[Serializable]
public struct MyConfig
{
    public UInt16 level;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
    public UInt16[] thresholds;
}
'@

Add-Type -TypeDefinition $typeCode

# 初始化结构体
$config = New-Object MyConfig
$config.level = 1
$config.thresholds = New-Object UInt16[] 16

# 填充数组数据
for ($i = 0; $i -lt 16; $i++) {
    $config.thresholds[$i] = [UInt16]($i + 1)
}

# 序列化并写入文件
$structSize = [System.Runtime.InteropServices.Marshal]::SizeOf($config)
$ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($structSize)
try {
    [System.Runtime.InteropServices.Marshal]::StructureToPtr($config, $ptr, $false)
    $byteArray = New-Object byte[] $structSize
    [System.Runtime.InteropServices.Marshal]::Copy($ptr, $byteArray, 0, $structSize)
    [System.IO.File]::WriteAllBytes("MyConfig.bin", $byteArray)
    Write-Host "结构体已成功写入MyConfig.bin"
}
finally {
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
}

内容的提问来源于stack exchange,提问作者Richard W

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:50:35