忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

VB.NET:マーシャリングを使用した、バイト配列から構造体へのコピー
VB.NETで通信制御プログラムを組んでいると、電文解析などが必要になります。電文はバイト配列で取得しますが、 その電文を分割して処理するにも、解析用の構造体を宣言しそちらにバイト配列からコピーできると便利です。
今回は、構造体に4個のバイト配列変数を持った簡単な構造を例にとります。以下の様な宣言になります。 各変数は「MarshalAs」を使って、固定サイズ長を宣言してやります。

'バイト配列分解構造体
<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Private Structure ByteSplit
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> _
    Public A As Byte()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _
    Public B As Byte()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _
    Public C As Byte()
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=64)> _
    Public X As Byte()
End Structure


バイト配列からこの構造体に変換する関数を以下に示します。

■「clsSqlServer」のソース
Imports System.Runtime.InteropServices  'これは先頭で宣言してください

''' 
''' バイト配列を構造体にコピーする
''' 
''' <param name="bytes">バイト配列</param>
''' <returns>構造体を返す</returns>
Private Function ToByteSplit(ByVal bytes As Byte()) As ByteSplit
    '作業用Byte配列(この時点でnewBytesの内容は全て0設定)
    Dim newBytes As Byte() = New Byte(Marshal.SizeOf(GetType(ByteSplit)) - 1) {}
    '作業用Byte配列にコピー
    Array.Copy(bytes, newBytes, bytes.Length)
    '作業用Byte配列をガベージコレクタが移動できない様に固定
    Dim gch As GCHandle = GCHandle.Alloc(newBytes, GCHandleType.Pinned)
    '構造体へコピー
    Dim result As ByteSplit = CType(Marshal.PtrToStructure(gch.AddrOfPinnedObject(), GetType(ByteSplit)), ByteSplit)
    '固定ハンドルの廃棄
    gch.Free()
    '構造体を返す
    Return result
End Function

'バイト配列を構造体にコピーするのテスト
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
    Dim x As Byte() = New Byte() {&H10, &H11, &H20, &H21, &H22, &H23, &H30, &H31, &H32, &H33, &H40, &H41}
    Dim xByte As ByteSplit = ToByteSplit(x)
End Sub


処理ボタンをフォームに貼り付けてテストしていますが、「x」で12個のデータを宣言していますが、 構造体の「X」には「&H40, &H41」の部分しか設定されませんが、残りには&H0が埋められます。

=====
2015/03/19:の時の情報











PR

コメント

コメントを書く