• 検索結果がありません。

構造体

N/A
N/A
Protected

Academic year: 2021

シェア "構造体"

Copied!
8
0
0

読み込み中.... (全文を見る)

全文

(1)

■ Byte 配列→構造体とコピーする方法 構造体とバイト配列の変換を行うには、System.Runtime.InteropServices 名前空間をインポートして 置くと便利で有る。 Visual Basic Imports System.Runtime.InteropServices C# using System.Runtime.InteropServices; 下記の3 種類の構造体にバイト配列の値を格納した場合に付いて検証する。Type1 構造体は総ての要素

がShort 型の場合で、Type2 と Type3 は最初の要素が Short 型、2 番目の要素が Integer 型、3 番目と 4 番目の要素が Bute 型で、構造体の長さ(総バイト数)は孰れも 8 バイトで有る。猶、3 番目の構造体 は System.Runtime.InteropServices.StructLayout 属性で構造体のメモリ内での配置をカスタマイズ して居る。

Visual Basic Private Structure Type1

Dim Item1 As Short Dim Item2 As Short Dim Item3 As Short Dim Item4 As Short End Structure

Private Structure Type2 Dim Item1 As Short Dim Item2 As Integer Dim Item3 As Byte Dim Item4 As Byte End Structure

<StructLayout(LayoutKind.Sequential, Pack:=1)> Structure Type3 Dim Item1 As Short

Dim Item2 As Integer Dim Item3 As Byte Dim Item4 As Byte End Structure

C# private struct type1

{

public short item1; public short item2; public short item3; public short item4; }

(2)

private struct type2 {

public short item1; public int item2; public byte item3; public byte item4; }

[StructLayout(LayoutKind.Sequential,Pack=1)] private struct type3

{

public short item1; public int item2; public byte item3; public byte item4; } 因みに、System.Runtime.InteropServices.StructLayout 属性で指定する LayoutKind 列挙型は、下記 の通りで有る。 属性 解説 Auto ランタイムは、アンマネージメモリ内のオブジェクトのメンバに対して適切なレイアウ トを自動的に選択する。此の列挙体メンバで定義されたオブジェクトは、マネージコー ドの外に公開出来ない。公開しようとすると、例外が生成される。 Explicit アンマネージメモリ内に有るオブジェクトの各メンバの正確な位置は、明示的に制御さ れる。各メンバはFieldOffsetAttribute を使用して、其の型内のフィールドの位置を指 定する必要が有る。 Sequential オブジェクトのメンバは、アンマネージメモリにエクスポートする時に表示される順番 に従ってレイアウトされる。メンバは、StructLayoutAttribute.Pack で指定したパッキ ングに従ってレイアウトされる。メンバは非連続に出来る。 上記の夫々の構造体に格納するバイト配列の各要素の値は、下記の通りで有る。 25H 52H 9AH 44H 16H 42H 21H 2CH 上記に対して、下記のコードを実行した結果を検証して観る。 Visual Basic

Dim B() As Byte = {&H25, &H52, &H9A, &H44, &H16, &H42, &H21, &H2C} Dim T1 As Type1

Dim T2 As Type2 Dim T3 As Type3

Dim P1 As System.IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Type1))) Dim P2 As System.IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Type2))) Dim P3 As System.IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(Type3))) Marshal.Copy(B, 0, P1, B.Length)

Marshal.Copy(B, 0, P2, B.Length) Marshal.Copy(B, 0, P3, B.Length)

(3)

T2 = DirectCast(Marshal.PtrToStructure(P2, GetType(Type2)), Type2) T3 = DirectCast(Marshal.PtrToStructure(P3, GetType(Type3)), Type3) System.Runtime.InteropServices.Marshal.FreeHGlobal(P1) System.Runtime.InteropServices.Marshal.FreeHGlobal(P2) System.Runtime.InteropServices.Marshal.FreeHGlobal(P3) C# byte[] b = { 0x25, 0x52, 0x9A, 0x44, 0x16, 0x42, 0x21, 0x2C }; type1 t1; type2 t2; type3 t3; IntPtr p1 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(type1))); IntPtr p2 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(type2))); IntPtr p3 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(type3))); Marshal.Copy(b, 0, p1, b.Length); Marshal.Copy(b, 0, p2, b.Length); Marshal.Copy(b, 0, p3, b.Length); t1 = (type1)Marshal.PtrToStructure(p1, typeof(type1)); t2 = (type2)Marshal.PtrToStructure(p2, typeof(type2)); t3 = (type3)Marshal.PtrToStructure(p3, typeof(type3)); Marshal.FreeHGlobal(p1); Marshal.FreeHGlobal(p2); Marshal.FreeHGlobal(p3); 上記のコードを実行して、DataGridView コントロールに各構造体の要素を表示したのが下図で有る。 Type1 構造体の様に各要素が同じデータ型で有れば正しく格納されるが、Type2 構造体の様に各要素の データ型が異なれば正しく格納されない。亦、Type3 構造体の様にアライメントを指定して構造体を定 義すると、正しく格納される。猶、Pack:=1 の部分を、Pack:=2、Pack:=4、Pack:=8 とすると、何う 成るかも示して置く。 Pack:=1

(4)

Pack:=2

Pack:=4

(5)

■ 構造体→Byte 配列とコピーする方法

下記の構造体の値をバイト配列に格納した場合に付いて検証する。構造体は要素は総て最も問題と成る 固定長のString 型にして有る。猶、構造体は System.Runtime.InteropServices.StructLayout 属性で

構造体のメモリ内での配置をカスタマイズして居り、亦、固定長文字列を必要とするVisual Basic のフ

ァイル入出力関数(FileGet や FilePut 等)を使う時の為に、VBFixedStringAttribute 属性を使用して 居る。其の為、C#では、Visual Basic の参照設定を追加して置く必要が有る。猶、此の構造体には、構 造体の要素をバイト配列に格納する為のユーザー定義関数(Getbyte)が含まれて居る。

Visual Basic

<StructLayout(LayoutKind.Sequential, Pack:=1)> Structure Buffer

<VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Dim Item1 As String

<VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Dim Item2 As String

Function Getbyte(ByVal Data As Buffer) As Byte() Dim Num As Integer

Dim Cnt As Integer Dim Buf() As Byte Dim Tmp() As Byte Num = Marshal.SizeOf(Data) ReDim Buf(Num - 1) Cnt = 0 Tmp = System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(Data.Item1) For I As Integer = 0 To (Tmp.Length - 1)

If Cnt > Buf.Length - 1 Then Exit For Buf(Cnt) = Tmp(I) : Cnt += 1

Next

Tmp = System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(Data.Item2) For I As Integer = 0 To (Tmp.Length - 1)

If Cnt > Buf.Length - 1 Then Exit For Buf(Cnt) = Tmp(I) : Cnt += 1 Next Getbyte = Buf End Function End Structure C# [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct buffer

{

[VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)] public string item1;

[VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst=3)] public string item2;

public byte[] Getbyte(buffer data) {

int num; int cnt; byte[] buf;

(6)

byte[] tmp;

num = Marshal.SizeOf(data); buf = new byte[num];

cnt = 0;

tmp = System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(data.item1); for (int i = 0; i < tmp.Length; i++)

{

if (cnt > buf.Length - 1) break; buf[cnt] = tmp[i]; cnt++; }

tmp = System.Text.Encoding.GetEncoding("SHIFT_JIS").GetBytes(data.item2); for (int i = 0; i < tmp.Length; i++)

{ if (cnt > buf.Length - 1) break; buf[cnt] = tmp[i]; cnt++; } return buf; } } 因みに、VBFixedStringAttribute 属性は、文字列の長さを文字数ではなくバイト数で指定する。猶、 System.Runtime.InteropServices.StructLayout 属性に付いては前項を参照され度い。 上記に対して、下記のコードを実行した結果を検証して観る。 Visual Basic Dim B() As Byte Dim T As Buffer With T .Item1 = txtItem1.Text .Item2 = txtItem2.Text End With B = T.Getbyte(T) lstDisp.Items.Clear()

For I As Integer = 0 To (B.Length - 1)

lstDisp.Items.Add(B(I).ToString("X").PadLeft(2, "0"c) & " - " & Chr(B(I))) Next C# byte[] b; buffer t; t.item1 = txtItem1.Text; t.item2 = txtItem2.Text;

(7)

b = t.Getbyte(t); lstDisp.Items.Clear();

for (int i = 0; i < b.Length; i++) { lstDisp.Items.Add(b[i].ToString("X").PadLeft(2, '0') + " - " + System.Convert.ToChar(b[i]).ToString()); } 上記のコードを実行して、ListBox コントロールにバイト配列の要素を表示したのが下図で有る。 構造体の夫々の要素が、VBFixedStringAttribute 属性で指定したバイト数と等しい時は、正しく格納 されるが、等しくない時は正しく格納されない。 此れは、VBFixedStringAttribute 属性は、此の属性に対応するメソッド(固定長文字列を必要とする Visual Basic の FileGet や FilePut 等のファイル入出力関数)等に対する情報提供の為の属性で、可変 長の文字列を固定長の文字列に変換する訳ではないからで有る。

従って、Visual Basic の FileSystem を使用してファイルに書き込めば、VBFixedStringAttribute 属性 で指定したバイト数と等しくない要素の値も正しく保存される。下記のコードでは、書き込んだファイ ルからバイト配列に読み込んで確認して居る。

構造体のユーザー定義関数(Getbyte)の中で、各要素のバイト数を Marshal.SizeOf メソッドで取得し、

其のバイト数丈をバイト配列に格納する事が出来れば良いのだが、String 型の要素の場合はサイズを取

(8)

Visual Basic Dim B() As Byte Dim T As Buffer With T .Item1 = txtItem1.Text .Item2 = txtItem2.Text End With

Dim F As String = Application.StartupPath If Not F.EndsWith("¥") Then F &= "¥" F &= "temp.rnd" FileOpen(1, F, OpenMode.Random, , , 6) FilePut(1, T, 1) FileClose(1) B = Microsoft.VisualBasic.FileIO.FileSystem.ReadAllBytes(F) Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile(F) lstDisp.Items.Clear()

For I As Integer = 0 To (B.Length - 1)

lstDisp.Items.Add(B(I).ToString("X").PadLeft(2, "0"c) & " - " & Chr(B(I))) Next C# byte[] b; buffer t; t.item1 = txtItem1.Text; t.item2 = txtItem2.Text; string f = Application.StartupPath; if (!f.EndsWith(@"¥")) f += @"¥"; f += "temp.rnd";

FileSystem.FileOpen(1, f, OpenMode.Random, OpenAccess.Write, OpenShare.Default, 6); FileSystem.FilePut(1, t, 1);

FileSystem.FileClose(1);

b = Microsoft.VisualBasic.FileIO.FileSystem.ReadAllBytes(f); Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile(f);

lstDisp.Items.Clear();

for (int i = 0; i < b.Length; i++) {

lstDisp.Items.Add(b[i].ToString("X").PadLeft(2, '0') + " - " + System.Convert.ToChar(b[i]).ToString());

参照

関連したドキュメント

Murota: Discrete Convex Analysis (SIAM Monographs on Discrete Mathematics and Applications 10, SIAM, 2003).

Figures 10 and 11 show the mean and the coefficient of variation of the waiting time as a function of g2 for the NPNV model, where we assume that Pl P2 P3- P4 0.1, that the batch

NISSEI RED EXHIBITION in Nagano2022”

つまり、p 型の語が p 型の語を修飾するという関係になっている。しかし、p 型の語同士の Merge

本プロジェクトでは、海上技術安全研究所で開発された全船荷重・構造⼀貫強度評価システム (Direct Load and Structural Analysis

建屋構造 鉄⾻造、鉄筋コンクリート、鋼板コンクリート等、遮蔽機能と⼗分な強度を有 する構造

参考第 1 表 中空断面構造物の整理結果(7 号炉 ※1 ) 構造物名称 構造概要 基礎形式 断面寸法

1.6.1-3 に⽰すように、ハルモニタリング、データ同化、健全性評価の⼀連のフローからなる