- - PR -
VB.NETで文字列の構造体をバイト配列へコピーする方法
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2006-08-10 16:13
VB.NET2005において、構造体をバイト配列へコピーする方法で
正しくコピー出来ないで困っています。 下記コードを実行すると bdata(0)=49 bdata(1)=50 bdata(2)=0 bdata(3)=52 bdata(4)=53 bdata(5)=0 の結果になります。 望んでいる結果は bdata(0)=49 bdata(1)=50 bdata(2)=0 bdata(3)=52 bdata(4)=53 bdata(5)=0 です。 ---------------------------コード <StructLayout _ (LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _ Public Structure BUF <VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> Public data1 As String <VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> Public data2 As String End Structure Dim sendbuf As BUF Dim bdata As Byte() With sendbuf .data1 = "123" .data2 = "456" End With Dim size As Integer = Marshal.SizeOf(sendbuf) Dim buffer As IntPtr = Marshal.AllocCoTaskMem(size) Marshal.StructureToPtr(sendbuf, buffer, True) ReDim bdata(size - 1) Marshal.Copy(buffer, bdata, 0, size) ------------------------------------- |
|
投稿日時: 2006-08-10 16:15
すいませんでした。
一部誤りがありましたので訂正します。 望んでいる結果は bdata(0)=49 bdata(1)=50 bdata(2)=51 bdata(3)=52 bdata(4)=53 bdata(5)=54 です。 |
|
投稿日時: 2006-08-10 16:15
すいませんでした。
一部誤りがありましたので訂正します。 望んでいる結果は bdata(0)=49 bdata(1)=50 bdata(2)=51 bdata(3)=52 bdata(4)=53 bdata(5)=54 です。 |
|
投稿日時: 2006-08-10 17:41
必ず終端文字が含まるようになっているので String じゃ無理ですね。
// 「正しくコピーできない」わけではありません。 Byte 配列にして ByValArray にして入れるときに Encoding クラス使うとか。 String のプロパティ作って、フィールドに格納するときに Encoding 施すってのはどうかなー。 |
|
投稿日時: 2006-08-10 18:09
返事有難うございます。
>>必ず終端文字が含まるようになっているので String じゃ無理ですね。 >>// 「正しくコピーできない」わけではありません。 ●Structure時での指定を変えるなどして終端文字(Null)が含まれないように 出来ないのでしょうか。 >>Byte 配列にして ByValArray にして入れるときに Encoding クラス使うとか。 >>String のプロパティ作って、フィールドに格納するときに Encoding 施すってのはどうかなー。 ●意味がいまいち理解出来ていないのですが、Encoding クラスをどのように 使うのでしょうか。 |
|
投稿日時: 2006-08-10 23:18
文字列が終端子を必ず含むからです(でなければ、どこで終わったらいいのかわからない)。
C 言語使いなら、1度は痛い思いをしているはずのところなので、よく分かるんですけどね。 なので、終端子を含まないようにする必要があります。それは結構簡単で、「文字列」ではなく、「文字配列」にしてやればいいわけです。 ただし、「変数 = "123"」という使い方は、出来なくなります(手間だけど、そんなに難しくはない)。あ、プロパティ作るってか。なるほど!! 構造体って、VB.NET では class と変わらないんですよ。 そういえば、ASCII 7bit の範囲の文字だけを使うなら問題ないですが、それ以外の文字も使うなら、問題になるかもしれませんね。→エンコード |
|
投稿日時: 2006-08-11 10:49
下記コードで望んだ結果を配列にセットすることが出来ました。
とりあえず最初に望んだ結果になったのですが、構造体のメンバ数が 増えると同じような処理のコードをメンバ数分繰り返し書かないと いけないのが難点ですが。。。 コード------------------------------------------------------------------------- <StructLayout _ (LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _ Public Structure BUF <VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> Public data1 As String <VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> Public data2 As String Function Getbyte(ByVal sendbuf As BUF) As Byte() Dim size As Integer Dim bdatabuf As Byte() Dim bdatabuf1 As Byte() Dim i As Integer Dim cnt As Integer size = Marshal.SizeOf(sendbuf) ReDim bdatabuf(size - 1) cnt = 0 bdatabuf1 = Encoding.GetEncoding("SHIFT_JIS").GetByte(sendbuf.data1) For i = 0 To UBound(bdatabuf1) bdatabuf(cnt) = bdatabuf1(i) cnt = cnt + 1 Next bdatabuf1 = Encoding.GetEncoding("SHIFT_JIS").GetByte(sendbuf.data2) For i = 0 To UBound(bdatabuf1) bdatabuf(cnt) = bdatabuf1(i) cnt = cnt + 1 Next Getbyte = bdatabuf End Function End Structure Dim sendbuf2 As BUF Dim bdata2 As Byte() With sendbuf2 .data1 = "1234" .data2 = "456" '.data1 = "あ3" '.data2 = "い6" End With bdata2 = sendbuf2.Getbyte(sendbuf2) |
|
投稿日時: 2006-08-11 22:14
VB.NET とネイティブの間でどのような変換がされるのか、調べていないので不確かですが。。。
本当に大丈夫ですか?「文字列」と、「文字配列」は違います。「文字列」には、必ず終端子が入ります。サイズには、終端しも含まなければなりません。ただし、文字数には終端子は含まれません。 しかし、「文字配列」は、そもそも終端子がありません。1文字しか入らない箱が並んでいるだけですから。文字配列を文字列のように扱えるのは、配列が必ず連続したアドレスに割り振られるからです。 いま、UnmanagedType.ByValTStr, SizeConst:=3 と、文字列でサイズを3と指定していますが、このサイズには終端子が含まれなければなりません。3文字埋めてしまうと、終端子がなくなって、文字列の終わりを判別できなくなるような気がします。 |