tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル構造体のメモリコピー
記事No1253
投稿日: 2005/01/06(Thu) 17:05
投稿者mikiko
[OSのVer]:Windows  xp   [VBのVer]:VB.NET  
MSG_BUFFERの内容を開始位置とコピーバイト数を指定して
recv_area1またはrecv_area2に開始位置とコピーバイト数を
指定してコピーしたいのですができるでしょうか?

    Structure MSG_BUFFER
        Public M_Buffer_Area() As Byte  
        Public Sub Initialize()
            ReDim M_Buffer_Area(10240)
        End Sub
    End Structure

structue recv_area1
  public a as integer
  public b as string      '*10
end structure

structue recv_area2
  public c as string       '* 20
end structure

[ツリー表示へ]
タイトルRe: 構造体のメモリコピー
記事No1254
投稿日: 2005/01/06(Thu) 17:29
投稿者るしぇ
…構造体も…メモリコピーも関係なく
特定のバイト配列を文字列に変換したいなら
System.Text.Encoding クラスを使ってみて下さい。

[ツリー表示へ]
タイトルRe^2: 構造体のメモリコピー
記事No1263
投稿日: 2005/01/07(Fri) 16:33
投稿者mikiko
[OSのVer]:Windows    [VBのVer]:VB.NET  
> …構造体も…メモリコピーも関係なく
> 特定のバイト配列を文字列に変換したいなら
> System.Text.Encoding クラスを使ってみて下さい。
返信ありがとうございます。
言葉足らずで、すみません。
stringだけでなく integer部分を含むすべてにコピーしたいのです。

[ツリー表示へ]
タイトルRe^3: 構造体のメモリコピー
記事No1268
投稿日: 2005/01/08(Sat) 11:20
投稿者るしぇ
API の MoveMemory を使うとか、
Cで自前のDLLを作って呼び出すとか、
でできます。

[ツリー表示へ]
タイトルRe^3: 構造体のメモリコピー
記事No1269
投稿日: 2005/01/11(Tue) 10:00
投稿者魔界の仮面弁士
> stringだけでなく integer部分を含むすべてにコピーしたいのです。

なぜ、メモリコピーが必要なのかが分からなかったので、
具体的な回答を付け難いのですが、さしあたっては
  System.Runtime.InteropServices.MarshalAsAttribute 属性クラス
  System.Runtime.InteropServices.StructLayoutAttribute 属性クラス
などを使って、各メンバのサイズと構造体の大きさを明示化してください。

その上で、
  System.Runtime.InteropServices.Marshal クラス
のメソッドを使えば、メモリコピーが可能かと思います。

[ツリー表示へ]
タイトルRe^4: 構造体のメモリコピー
記事No1270
投稿日: 2005/01/11(Tue) 17:31
投稿者魔界の仮面弁士
さしあたり、「原始的」な方法を。


  Dim Buf As MSG_BUFFER
  Dim Area1 As recv_area1

  '取得元となるサンプルデータ
  Buf.Initialize()
  Buf.M_Buffer_Area(0) = &HD2
  Buf.M_Buffer_Area(1) = &H2
  Buf.M_Buffer_Area(2) = &H96
  Buf.M_Buffer_Area(3) = &H49
  Buf.M_Buffer_Area(4) = &HE5
  Buf.M_Buffer_Area(5) = &HBC
  Buf.M_Buffer_Area(6) = &H81
  Buf.M_Buffer_Area(7) = &HE5
  Buf.M_Buffer_Area(8) = &HA3
  Buf.M_Buffer_Area(9) = &HAB


  '0番目の位置から10バイト分を読み込み、個別に変換
  With New IO.BinaryReader(New IO.MemoryStream(Buf.M_Buffer_Area, 0, 10))
      Area1.a = .ReadInt32()
      Area1.b = System.Text.Encoding.UTF8.GetString(.ReadBytes(6))
      .Close()
  End With

[ツリー表示へ]
タイトルRe^5: 構造体のメモリコピー
記事No1275
投稿日: 2005/01/13(Thu) 16:27
投稿者mikiko
[OSのVer]:Windows    [VBのVer]:VB.NET  
> さしあたり、「原始的」な方法を。
>
>
>   Dim Buf As MSG_BUFFER
>   Dim Area1 As recv_area1
>
>   '取得元となるサンプルデータ
>   Buf.Initialize()
>   Buf.M_Buffer_Area(0) = &HD2
>   Buf.M_Buffer_Area(1) = &H2
>   Buf.M_Buffer_Area(2) = &H96
>   Buf.M_Buffer_Area(3) = &H49
>   Buf.M_Buffer_Area(4) = &HE5
>   Buf.M_Buffer_Area(5) = &HBC
>   Buf.M_Buffer_Area(6) = &H81
>   Buf.M_Buffer_Area(7) = &HE5
>   Buf.M_Buffer_Area(8) = &HA3
>   Buf.M_Buffer_Area(9) = &HAB
>
>
>   '0番目の位置から10バイト分を読み込み、個別に変換
>   With New IO.BinaryReader(New IO.MemoryStream(Buf.M_Buffer_Area, 0, 10))
>       Area1.a = .ReadInt32()
>       Area1.b = System.Text.Encoding.UTF8.GetString(.ReadBytes(6))
>       .Close()
>   End With
ありがとうございます。
 いろいろ教えていただいて勉強になります。
 個別対応は最後の手段としたいと思います。
 
 
 
 

[ツリー表示へ]
タイトルRe^6: 構造体のメモリコピー
記事No1278
投稿日: 2005/01/14(Fri) 12:57
投稿者魔界の仮面弁士
# 全文引用は不要かと。

>  個別対応は最後の手段としたいと思います。
う〜ん。原始的な方法は「最初の手段」ではなく、「最後の手段」ですか。(^^;

という事は、個別に割り当てる方法は、できる限り使いたくない。
メンバ全体を一括で渡したい――という事ですね。
その場合の対処方法は、先の回答(No.1269)に書いた通りですよ。

すなわち、System.Runtime.InteropServices.Marshal を使う事になります。
(MarshalクラスのCopyメソッドは、MoveMemory APIと同様の働きをします)


ただしそのままでは、文字列型のサイズや文字コードなどが未定義なので、
各種属性を用いて、構造体の定義に手を加える必要があります。


いずれにしても、Marshalクラスは、マーシャリングのために用意されたクラスなので、
P/Invoke以外の目的で使うのはお奨めしません。アンマネージドですしね。

API呼び出し用の構造体ではなく、.NETの世界だけで用いる構造体ならば、
『BinaryReaderを渡すと、それを個別のメンバに割り当てるメソッド』を
用意する方が、分かりやすくスマートかと思いますよ。


そもそも、『構造体のメモリコピーが必要な理由』って何なのでしょうか?
それがわかれば、より良い回答ができるかも。(^-^A

[ツリー表示へ]
タイトルRe^7: 構造体のメモリコピー
記事No1280
投稿日: 2005/01/14(Fri) 14:37
投稿者魔界の仮面弁士
> すなわち、System.Runtime.InteropServices.Marshal を使う事になります。

説明は不要かと思いますが、折角なので、Marshalクラスによるサンプルも書いておきます。


'=== マーシャリング用に、文字列長などの情報を付加しておく ===
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)> _
Public Structure recv_area1
  Public a As Integer
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> _
  Public b As String
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure recv_area2
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=20)> _
  Public c As String
End Structure


'=== 以下、操作用のコード ===
  Dim Buf As MSG_BUFFER
  Dim Area1 As recv_area1
  Dim Area2 As recv_area2

  '取得元となるサンプルデータ
  Buf.M_Buffer_Area = New Byte() { _
      &HD2, &H2, &H96, &H49, _
      &HB5, &H30, &HF3, &H30, &HD7, &H30, &HEB, &H30, &HC7, &H30, _
      &HFC, &H30, &HBF, &H30, &H67, &H30, &H59, &H30, &H2, &H30, _
      &HC2, &H53, &H3, &H80, &H6B, &H30, &H6A, &H30, &H8A, &H30, _
      &H7E, &H30, &H59, &H30, &H4B, &H30, &H6D, &H30, &H3F, &H0 _
  }

  Dim IPtr As IntPtr, O As Object
  Dim BufSize As Integer

  '0番目の位置から recv_area1 に読み込む
  BufSize = Marshal.SizeOf(Area1)
  IPtr = Marshal.AllocHGlobal(BufSize)
  Marshal.Copy(Buf.M_Buffer_Area, 0, IPtr, BufSize)
  O = Marshal.PtrToStructure(IPtr, GetType(recv_area1))
  Area1 = DirectCast(O, recv_area1)
  Marshal.FreeHGlobal(IPtr)

  '4番目の位置から recv_area2 に読み込む
  BufSize = Marshal.SizeOf(Area2)
  IPtr = Marshal.AllocHGlobal(BufSize)
  Marshal.Copy(Buf.M_Buffer_Area, 4, IPtr, BufSize)
  O = Marshal.PtrToStructure(IPtr, GetType(recv_area2))
  Area2 = DirectCast(O, recv_area2)
  Marshal.FreeHGlobal(IPtr)

  'recv_area1, recv_area2 の内容を確認
  Trace.WriteLine("recv_area1.a = " & Area1.a)
  Trace.WriteLine("recv_area1.b = " & Area1.b)
  Trace.WriteLine("recv_area2.c = " & Area2.c)

[ツリー表示へ]
タイトルRe^8: 構造体のメモリコピー
記事No1281
投稿日: 2005/01/14(Fri) 15:32
投稿者mikiko
[OSのVer]:Windows    [VBのVer]:VB.NET  
サンプルまで書いていただいてありがとうございます。
おかげでよくわかりました。
まだ、.netをはじめたばかりなのでNo.1269の回答を頂いたときは
具体的にどうすればよいのかわからずいろいろ調べていました。
メモリコピーが必要な理由ですが
コピー元は、受信電文です。
電文のヘッダー部分により、コピー先構造体が変わります。(recv_area1 or recv_area2 or
recv_area3...)
電文の数は200くらいあります。なので個別対応はさけたいのです。
もともとvb4.0のシステムで、以前は構造体メモリコピーはcで作成したdllで行っていました。
今回は使いません。
No1280の方法だとあとはselect case を追加するだけですね。
ありがとうございました。

[ツリー表示へ]