尋找訪問單個陣列元素的方法(此問題的繼續)
$CSharpCode = @"
using System;
namespace TestStructure
{
public struct TestStructure
{
public byte Field1;
public unsafe fixed byte Field2[4];
}
}
"@
$cp = New-Object System.CodeDom.Compiler.CompilerParameters
$cp.CompilerOptions = '/unsafe'
Add-Type -TypeDefinition $CSharpCode -CompilerParameters $cp
function ConvertTo-Struct
{
# Only accept struct types (sealed value types that are neither primitive nor enum)
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ $_.IsValueType -and $_.IsSealed -and -not($_.IsPrimitive -or $_.IsEnum) })]
[Type]$TargetType,
[Parameter(Mandatory = $true)]
[byte[]]$BinaryData
)
# Start by calculating minimum size of the underlying memory allocation for the new struct
$memSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type]$TargetType)
# Make sure user actually passed enough data to initialize struct
if($memSize -gt $BinaryData.Length){
Write-Error "Not enough binary data to create an instance of [$($TargetType.FullName)]"
return
}
# now we just need some unmanaged memory in which to create our struct instance
$memPtr = [IntPtr]::Zero
try {
$memPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($memSize)
# copy byte array to allocated unmanaged memory from previous step
[System.Runtime.InteropServices.Marshal]::Copy($BinaryData, 0, $memPtr, $memSize)
# then marshal the new memory region as a struct and return
return [System.Runtime.InteropServices.Marshal]::PtrToStructure($memPtr, [type]$TargetType)
}
finally {
# and finally remember to clean up the allocated memory
if($memPtr -ne [IntPtr]::Zero){
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($memPtr)
}
}
}
$testStructure = ConvertTo-Struct -TargetType ([TestStructure.TestStructure]) -BinaryData (1..100 -as [byte[]])
$testStructure.Field1
$testStructure.Field2
這會產生以下輸出:
1
FixedElementField
-----------------
2
- 只有第一個陣列元素
$Field2是可見的,不能訪問其他使用$testStructure.Field2[x]
尋找一種方法來迭代已知型別/大小的 FixedBuffer
$testStructure.Field2.GetType() 說<Field2>e__FixedBuffer0
$testStructure.Field2.FixedElementField.GetType() 是位元組
- 看不到訪問陣列其他元素的方法。
uj5u.com熱心網友回復:
PowerShell 的型別配接器實際上并沒有任何東西來處理unsafe fixed byte[]欄位,從底層型別系統的角度來看,實際上是原始指標。
底層記憶體分配的宣告大小僅存盤在元資料中,您可以按如下方式定位:
# Locate appropriate field metadata
$fieldInfo = $testStructure.GetType().GetField('Field2')
# Discover fixed buffer attribute
$fixedBufferAttribute = $fieldInfo.CustomAttributes.Where({$_.AttributeType -eq [System.Runtime.CompilerServices.FixedBufferAttribute]}) |Select -First 1
現在我們可以確定大小和預期的陣列元素型別:
if($fixedBufferAttribute)
{
# Grab array element type size from FixedBuffer attribute
$elemType,$size = $fixedBufferAttribute.ConstructorArguments
# Create array of appropriate size
$values = $elemType.MakeArrayType()::new($size)
# Copy values from fixed buffer pointer to managed array
try {
$fixedBufferHandle = [System.Runtime.InteropServices.GCHandle]::Alloc($TestStructure.Field2, 'Pinned')
[System.Runtime.InteropServices.Marshal]::Copy($fixedBufferHandle.AddrOfPinnedObject(), $values, 0, $size)
return $values
}
finally {
$fixedBufferHandle.Free()
}
}
您會發現$values現在包含預期的位元組值 2、3、4 和 5
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/454886.html
標籤:电源外壳
