Using an array of bytes with fixedoffset in a struct?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • sexauthor@gmail.com

    Using an array of bytes with fixedoffset in a struct?

    I'm converting a VB6 application over that called a 3rd party DLL with
    specific data structures. The VB6 code defined custom types for those
    data structures (ie: one with the specific data types, then one as a
    word array, and one as a byte array, for use in generating CRCs etc)
    and would LSet one to the other to copy data over.

    Naturally we can't do that in .NET. I've done lots of reading in the
    interoperabilit y books and the closest thing I've been able to come up
    with is:

    Public Const dmq_s_user_data As Integer = 20 ' bytes

    <StructLayout(L ayoutKind.Expli cit)Structure dmq_user_struct
    ' <FieldOffset(0) <VBFixedString( dmq_s_user_data )Dim
    dmq_b_user_data () As Byte
    ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
    sizeconst:=dmq_ s_user_data, arraysubtype:=U nmanagedType.As Any)Dim
    dmq_b_user_data () As Byte
    ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal TStr,
    sizeconst:=dmq_ s_user_data)Dim dmq_b_user_data () As Byte

    <FieldOffset(0) Dim dmq_l_user_1 As Integer
    <FieldOffset(4) Dim dmq_l_user_2 As Integer
    <FieldOffset(8) Dim dmq_l_user_3 As Integer
    <FieldOffset(12 )Dim dmq_l_user_4 As Integer
    <FieldOffset(16 )Dim dmq_l_user_5 As Integer

    Public Sub Initialize()
    ' ReDim dmq_b_user_data (dmq_s_user_dat a)
    End Sub
    End Structure 'dmq_user_struc t

    You can see there's the data itself, plus commented out ways of
    defining access to the data as a byte array. You can compile any of
    these to try, but you'll get an exception when you run it because
    arrays are a reference and you can't overlap references and values in
    structs like this.

    That's a huge problem for me. It turns out that in C# 2.0 you could
    define an array of bytes in-place with a "fixed" keyword. So in a
    structure you could have ...

    fixed byte dmq_b_user_data (dmq_s_user_dat a)

    And it would translate to something like ...

    byte dmq_b_user_data _1
    byte dmq_b_user_data _2
    byte dmq_b_user_data _3
    ... dmq_s_user_data

    Instead of being just a pointer to that array. I haven't been able to
    find anything in VB.NET, or any similar language construct to
    "fixed". I always get a pointer, and so I can't use that.

    I've read other suggestions to specifically define each byte as a
    reference type, but that's not going to work well for me seeing as
    some of these structures are really large and it would be too
    cumbersome.

    The other suggestion was define one structure with the named fields,
    and one structure of just the byte array, and use
    Marshal.Structu reToPtr and Marshal.Copy to copy the bytes from one to
    the other. I can do that, but this is a performance application and I
    don't want to unless I have to.

    Any comments, suggestions, hints, gripes from people with the same
    problem? I'd be particularly interested if there's been a "fixed" in-
    place array type introduced in VB.NET somewhere that I'm not aware
    of.

    Thanks.
  • Tom Shelton

    #2
    Re: Using an array of bytes with fixedoffset in a struct?

    On 2008-04-18, sexauthor@gmail .com <sexauthor@gmai l.comwrote:
    I'm converting a VB6 application over that called a 3rd party DLL with
    specific data structures. The VB6 code defined custom types for those
    data structures (ie: one with the specific data types, then one as a
    word array, and one as a byte array, for use in generating CRCs etc)
    and would LSet one to the other to copy data over.
    >
    Naturally we can't do that in .NET. I've done lots of reading in the
    interoperabilit y books and the closest thing I've been able to come up
    with is:
    >
    Public Const dmq_s_user_data As Integer = 20 ' bytes
    >
    ><StructLayout( LayoutKind.Expl icit)Structure dmq_user_struct
    ' <FieldOffset(0) <VBFixedString( dmq_s_user_data )Dim
    dmq_b_user_data () As Byte
    VBFixedString is not valid in interop scenarios. It is used by those
    crappy VB file functions.
    ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
    sizeconst:=dmq_ s_user_data, arraysubtype:=U nmanagedType.As Any)Dim
    dmq_b_user_data () As Byte
    ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal TStr,
    sizeconst:=dmq_ s_user_data)Dim dmq_b_user_data () As Byte
    >
    <FieldOffset(0) Dim dmq_l_user_1 As Integer
    <FieldOffset(4) Dim dmq_l_user_2 As Integer
    <FieldOffset(8) Dim dmq_l_user_3 As Integer
    <FieldOffset(12 )Dim dmq_l_user_4 As Integer
    <FieldOffset(16 )Dim dmq_l_user_5 As Integer
    >
    Public Sub Initialize()
    ' ReDim dmq_b_user_data (dmq_s_user_dat a)
    End Sub
    End Structure 'dmq_user_struc t
    >
    You can see there's the data itself, plus commented out ways of
    defining access to the data as a byte array. You can compile any of
    these to try, but you'll get an exception when you run it because
    arrays are a reference and you can't overlap references and values in
    structs like this.
    >
    That's a huge problem for me. It turns out that in C# 2.0 you could
    define an array of bytes in-place with a "fixed" keyword. So in a
    structure you could have ...
    >
    fixed byte dmq_b_user_data (dmq_s_user_dat a)
    >
    Yes C# 2.0 added that, but it can only be used in unsafe code - and has
    some other restrictions as well.
    And it would translate to something like ...
    >
    byte dmq_b_user_data _1
    byte dmq_b_user_data _2
    byte dmq_b_user_data _3
    ... dmq_s_user_data
    >
    Instead of being just a pointer to that array. I haven't been able to
    find anything in VB.NET, or any similar language construct to
    "fixed". I always get a pointer, and so I can't use that.
    >
    You won't - because VB.NET doesn't allow unsafe code, and that's the
    only place that fixed is legal in C#.
    I've read other suggestions to specifically define each byte as a
    reference type, but that's not going to work well for me seeing as
    some of these structures are really large and it would be too
    cumbersome.
    >
    The other suggestion was define one structure with the named fields,
    and one structure of just the byte array, and use
    Marshal.Structu reToPtr and Marshal.Copy to copy the bytes from one to
    the other. I can do that, but this is a performance application and I
    don't want to unless I have to.
    >
    Any comments, suggestions, hints, gripes from people with the same
    problem? I'd be particularly interested if there's been a "fixed" in-
    place array type introduced in VB.NET somewhere that I'm not aware
    of.
    >
    It might be helpful if you were to provide the C/C++ defintions of this
    structure. It's really hard to know what your doing with out seeing the
    original :)

    --
    Tom Shelton

    Comment

    • Bill McCarthy

      #3
      Re: Using an array of bytes with fixedoffset in a struct?

      Try something like :


      <StructLayout(L ayoutKind.Expli cit)Structure dmq_user_struct
      <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
      sizeconst:=dmq_ s_user_data, arraysubtype:=U nmanagedType.U1 )Dim
      dmq_b_user_data () As Byte

      '<FieldOffset(0 )Dim dmq_l_user_1 As Integer
      '<FieldOffset(4 )Dim dmq_l_user_2 As Integer
      '<FieldOffset(8 )Dim dmq_l_user_3 As Integer
      '<FieldOffset(1 2)Dim dmq_l_user_4 As Integer
      '<FieldOffset(1 6)Dim dmq_l_user_5 As Integer

      Public Sub Initialize()
      ReDim dmq_b_user_data (0 To dmq_s_user_data - 1)
      End Sub

      Private Const dmq_s_user_data As Integer = 20 ' bytes
      End Structure 'dmq_user_struc t




      <sexauthor@gmai l.comwrote in message
      news:85d93dfc-b832-4e8e-9510-8750b8714f10@a7 0g2000hsh.googl egroups.com...
      I'm converting a VB6 application over that called a 3rd party DLL with
      specific data structures. The VB6 code defined custom types for those
      data structures (ie: one with the specific data types, then one as a
      word array, and one as a byte array, for use in generating CRCs etc)
      and would LSet one to the other to copy data over.
      >
      Naturally we can't do that in .NET. I've done lots of reading in the
      interoperabilit y books and the closest thing I've been able to come up
      with is:
      >
      Public Const dmq_s_user_data As Integer = 20 ' bytes
      >
      <StructLayout(L ayoutKind.Expli cit)Structure dmq_user_struct
      ' <FieldOffset(0) <VBFixedString( dmq_s_user_data )Dim
      dmq_b_user_data () As Byte
      ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
      sizeconst:=dmq_ s_user_data, arraysubtype:=U nmanagedType.As Any)Dim
      dmq_b_user_data () As Byte
      ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal TStr,
      sizeconst:=dmq_ s_user_data)Dim dmq_b_user_data () As Byte
      >
      <FieldOffset(0) Dim dmq_l_user_1 As Integer
      <FieldOffset(4) Dim dmq_l_user_2 As Integer
      <FieldOffset(8) Dim dmq_l_user_3 As Integer
      <FieldOffset(12 )Dim dmq_l_user_4 As Integer
      <FieldOffset(16 )Dim dmq_l_user_5 As Integer
      >
      Public Sub Initialize()
      ' ReDim dmq_b_user_data (dmq_s_user_dat a)
      End Sub
      End Structure 'dmq_user_struc t
      >
      You can see there's the data itself, plus commented out ways of
      defining access to the data as a byte array. You can compile any of
      these to try, but you'll get an exception when you run it because
      arrays are a reference and you can't overlap references and values in
      structs like this.
      >
      That's a huge problem for me. It turns out that in C# 2.0 you could
      define an array of bytes in-place with a "fixed" keyword. So in a
      structure you could have ...
      >
      fixed byte dmq_b_user_data (dmq_s_user_dat a)
      >
      And it would translate to something like ...
      >
      byte dmq_b_user_data _1
      byte dmq_b_user_data _2
      byte dmq_b_user_data _3
      ... dmq_s_user_data
      >
      Instead of being just a pointer to that array. I haven't been able to
      find anything in VB.NET, or any similar language construct to
      "fixed". I always get a pointer, and so I can't use that.
      >
      I've read other suggestions to specifically define each byte as a
      reference type, but that's not going to work well for me seeing as
      some of these structures are really large and it would be too
      cumbersome.
      >
      The other suggestion was define one structure with the named fields,
      and one structure of just the byte array, and use
      Marshal.Structu reToPtr and Marshal.Copy to copy the bytes from one to
      the other. I can do that, but this is a performance application and I
      don't want to unless I have to.
      >
      Any comments, suggestions, hints, gripes from people with the same
      problem? I'd be particularly interested if there's been a "fixed" in-
      place array type introduced in VB.NET somewhere that I'm not aware
      of.
      >
      Thanks.

      Comment

      • Lloyd Sheen

        #4
        Re: Using an array of bytes with fixedoffset in a struct?


        "Tom Shelton" <tom_shelton@YO UKNOWTHEDRILLco mcast.netwrote in message
        news:unECIpWoIH A.552@TK2MSFTNG P06.phx.gbl...
        On 2008-04-18, sexauthor@gmail .com <sexauthor@gmai l.comwrote:
        >I'm converting a VB6 application over that called a 3rd party DLL with
        >specific data structures. The VB6 code defined custom types for those
        >data structures (ie: one with the specific data types, then one as a
        >word array, and one as a byte array, for use in generating CRCs etc)
        >and would LSet one to the other to copy data over.
        >>
        >Naturally we can't do that in .NET. I've done lots of reading in the
        >interoperabili ty books and the closest thing I've been able to come up
        >with is:
        >>
        >Public Const dmq_s_user_data As Integer = 20 ' bytes
        >>
        >><StructLayout (LayoutKind.Exp licit)Structure dmq_user_struct
        > ' <FieldOffset(0) <VBFixedString( dmq_s_user_data )Dim
        >dmq_b_user_dat a() As Byte
        >
        VBFixedString is not valid in interop scenarios. It is used by those
        crappy VB file functions.
        >
        > ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
        >sizeconst:=dmq _s_user_data, arraysubtype:=U nmanagedType.As Any)Dim
        >dmq_b_user_dat a() As Byte
        > ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal TStr,
        >sizeconst:=dmq _s_user_data)Di m dmq_b_user_data () As Byte
        >>
        > <FieldOffset(0) Dim dmq_l_user_1 As Integer
        > <FieldOffset(4) Dim dmq_l_user_2 As Integer
        > <FieldOffset(8) Dim dmq_l_user_3 As Integer
        > <FieldOffset(12 )Dim dmq_l_user_4 As Integer
        > <FieldOffset(16 )Dim dmq_l_user_5 As Integer
        >>
        > Public Sub Initialize()
        > ' ReDim dmq_b_user_data (dmq_s_user_dat a)
        > End Sub
        > End Structure 'dmq_user_struc t
        >>
        >You can see there's the data itself, plus commented out ways of
        >defining access to the data as a byte array. You can compile any of
        >these to try, but you'll get an exception when you run it because
        >arrays are a reference and you can't overlap references and values in
        >structs like this.
        >>
        >That's a huge problem for me. It turns out that in C# 2.0 you could
        >define an array of bytes in-place with a "fixed" keyword. So in a
        >structure you could have ...
        >>
        >fixed byte dmq_b_user_data (dmq_s_user_dat a)
        >>
        >
        Yes C# 2.0 added that, but it can only be used in unsafe code - and has
        some other restrictions as well.
        >
        >And it would translate to something like ...
        >>
        >byte dmq_b_user_data _1
        >byte dmq_b_user_data _2
        >byte dmq_b_user_data _3
        >... dmq_s_user_data
        >>
        >Instead of being just a pointer to that array. I haven't been able to
        >find anything in VB.NET, or any similar language construct to
        >"fixed". I always get a pointer, and so I can't use that.
        >>
        >
        You won't - because VB.NET doesn't allow unsafe code, and that's the
        only place that fixed is legal in C#.
        >
        >I've read other suggestions to specifically define each byte as a
        >reference type, but that's not going to work well for me seeing as
        >some of these structures are really large and it would be too
        >cumbersome.
        >>
        >The other suggestion was define one structure with the named fields,
        >and one structure of just the byte array, and use
        >Marshal.Struct ureToPtr and Marshal.Copy to copy the bytes from one to
        >the other. I can do that, but this is a performance application and I
        >don't want to unless I have to.
        >>
        >Any comments, suggestions, hints, gripes from people with the same
        >problem? I'd be particularly interested if there's been a "fixed" in-
        >place array type introduced in VB.NET somewhere that I'm not aware
        >of.
        >>
        >
        It might be helpful if you were to provide the C/C++ defintions of this
        structure. It's really hard to know what your doing with out seeing the
        original :)
        >
        --
        Tom Shelton
        MS has a tool or a link to one that will translate the C/C++ structs
        correctly for Dot.Net



        Hope this helps
        Lloyd Sheen

        Comment

        • Tom Shelton

          #5
          Re: Using an array of bytes with fixedoffset in a struct?

          On 2008-04-18, Lloyd Sheen <a@b.cwrote:
          >
          "Tom Shelton" <tom_shelton@YO UKNOWTHEDRILLco mcast.netwrote in message
          news:unECIpWoIH A.552@TK2MSFTNG P06.phx.gbl...
          >On 2008-04-18, sexauthor@gmail .com <sexauthor@gmai l.comwrote:
          >>I'm converting a VB6 application over that called a 3rd party DLL with
          >>specific data structures. The VB6 code defined custom types for those
          >>data structures (ie: one with the specific data types, then one as a
          >>word array, and one as a byte array, for use in generating CRCs etc)
          >>and would LSet one to the other to copy data over.
          >>>
          >>Naturally we can't do that in .NET. I've done lots of reading in the
          >>interoperabil ity books and the closest thing I've been able to come up
          >>with is:
          >>>
          >>Public Const dmq_s_user_data As Integer = 20 ' bytes
          >>>
          >>><StructLayou t(LayoutKind.Ex plicit)Structur e dmq_user_struct
          >> ' <FieldOffset(0) <VBFixedString( dmq_s_user_data )Dim
          >>dmq_b_user_da ta() As Byte
          >>
          >VBFixedStrin g is not valid in interop scenarios. It is used by those
          >crappy VB file functions.
          >>
          >> ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal Array,
          >>sizeconst:=dm q_s_user_data, arraysubtype:=U nmanagedType.As Any)Dim
          >>dmq_b_user_da ta() As Byte
          >> ' <FieldOffset(0) <MarshalAs(Unma nagedType.ByVal TStr,
          >>sizeconst:=dm q_s_user_data)D im dmq_b_user_data () As Byte
          >>>
          >> <FieldOffset(0) Dim dmq_l_user_1 As Integer
          >> <FieldOffset(4) Dim dmq_l_user_2 As Integer
          >> <FieldOffset(8) Dim dmq_l_user_3 As Integer
          >> <FieldOffset(12 )Dim dmq_l_user_4 As Integer
          >> <FieldOffset(16 )Dim dmq_l_user_5 As Integer
          >>>
          >> Public Sub Initialize()
          >> ' ReDim dmq_b_user_data (dmq_s_user_dat a)
          >> End Sub
          >> End Structure 'dmq_user_struc t
          >>>
          >>You can see there's the data itself, plus commented out ways of
          >>defining access to the data as a byte array. You can compile any of
          >>these to try, but you'll get an exception when you run it because
          >>arrays are a reference and you can't overlap references and values in
          >>structs like this.
          >>>
          >>That's a huge problem for me. It turns out that in C# 2.0 you could
          >>define an array of bytes in-place with a "fixed" keyword. So in a
          >>structure you could have ...
          >>>
          >>fixed byte dmq_b_user_data (dmq_s_user_dat a)
          >>>
          >>
          >Yes C# 2.0 added that, but it can only be used in unsafe code - and has
          >some other restrictions as well.
          >>
          >>And it would translate to something like ...
          >>>
          >>byte dmq_b_user_data _1
          >>byte dmq_b_user_data _2
          >>byte dmq_b_user_data _3
          >>... dmq_s_user_data
          >>>
          >>Instead of being just a pointer to that array. I haven't been able to
          >>find anything in VB.NET, or any similar language construct to
          >>"fixed". I always get a pointer, and so I can't use that.
          >>>
          >>
          >You won't - because VB.NET doesn't allow unsafe code, and that's the
          >only place that fixed is legal in C#.
          >>
          >>I've read other suggestions to specifically define each byte as a
          >>reference type, but that's not going to work well for me seeing as
          >>some of these structures are really large and it would be too
          >>cumbersome.
          >>>
          >>The other suggestion was define one structure with the named fields,
          >>and one structure of just the byte array, and use
          >>Marshal.Struc tureToPtr and Marshal.Copy to copy the bytes from one to
          >>the other. I can do that, but this is a performance application and I
          >>don't want to unless I have to.
          >>>
          >>Any comments, suggestions, hints, gripes from people with the same
          >>problem? I'd be particularly interested if there's been a "fixed" in-
          >>place array type introduced in VB.NET somewhere that I'm not aware
          >>of.
          >>>
          >>
          >It might be helpful if you were to provide the C/C++ defintions of this
          >structure. It's really hard to know what your doing with out seeing the
          >original :)
          >>
          >--
          >Tom Shelton
          >
          MS has a tool or a link to one that will translate the C/C++ structs
          correctly for Dot.Net
          >

          >
          Hope this helps
          Lloyd Sheen
          >
          Interesting... I always just do the conversions by hand :)

          --
          Tom Shelton

          Comment

          • sexauthor@gmail.com

            #6
            Re: Using an array of bytes with fixedoffset in a struct?

            Bill, I could do it like that but I then would not be able to access
            that byte array easily as Integers.
            It might be helpful if you were to provide the C/C++ defintions of this
            structure. It's really hard to know what your doing with out seeing the
            original :)
            >
            Ok, here is the VB6 code paraphrased by request. This is the simplest
            structure, the code has more complex ones but they all work on the
            same principle - lots of data values and then another type/struct that
            splits it by bytes or words.

            Public Const dmq_s_user_data As Long = 20

            Public Type dmq_user_string
            dmq_b_user_data (0 To dmq_s_user_data - 1) As Byte
            End Type 'dmq_user_strin g

            Public Type dmq_user_struct
            dmq_l_user_1 As Long
            dmq_l_user_2 As Long
            dmq_l_user_3 As Long
            dmq_l_user_4 As Long
            dmq_l_user_5 As Long
            End Type 'dmq_user_struc t

            Dim the_struct as dmq_user_struct
            Dim the_string As dmq_user_string

            ' Fill the struct
            the_struct.dmq_ l_user_1 = 100
            the_string.dmq_ l_user_2 = 200
            the_string.dmq_ l_user_3 = 200
            the_string.dmq_ l_user_4 = 200
            the_string.dmq_ l_user_5 = 200
            ' Convert it to a string
            the_string = LSet(the_struct )
            ' Pass it as an argument to a DLL
            ...

            Because I was really hurting to get this phase of the conversion
            project done last night, this is how I handled it. Clunky, but at
            least the app runs (milestone!). Note: this is not the line for line
            code, I actually managed to throw away the struct listed above and
            used this code on a different one, but I've changed the code to
            illustrate the technique.

            Option Strict Off
            Option Explicit On
            Imports System.Runtime. InteropServices
            Imports System.IO
            Imports System.Runtime. Serialization.F ormatters.Binar y
            Module Conversion

            Public Function RawSerialize(By Ref Anything As Object) As Byte()
            Call debug_message(8 0, "- Starting RawSerialize")
            Dim Size As Integer = Marshal.SizeOf( Anything)

            Dim RawDatas() As Byte
            ReDim RawDatas(Size)

            Dim Buffer As IntPtr
            Buffer = Marshal.AllocHG lobal(Size)

            Marshal.Structu reToPtr(Anythin g, Buffer, False)
            Marshal.Copy(Bu ffer, RawDatas, 0, Size)
            Marshal.FreeHGl obal(Buffer)
            RawSerialize = RawDatas

            Call debug_message(8 0, "- Ending RawSerialize")
            End Function

            Public Function RawDeserialize( ByVal RawDatas As Byte(), ByVal
            AnyType As Type) As Object
            Call debug_message(8 0, "- Starting RawDeserialize" )
            Dim Size As Integer = Marshal.SizeOf( AnyType)

            Dim Buffer As IntPtr
            Buffer = Marshal.AllocHG lobal(size)

            Marshal.Copy(Ra wDatas, 0, Buffer, Size)
            RawDeserialize = Marshal.PtrToSt ructure(Buffer, AnyType)
            Marshal.FreeHGl obal(Buffer)

            Call debug_message(8 0, "- Ending RawDeserialize" )
            End Function
            End Module

            <StructLayout(L ayoutKind.Seque ntial)Public Structure dmq_user_struct
            Dim dmq_l_user_1 As Integer
            Dim dmq_l_user_2 As Integer
            Dim dmq_l_user_3 As Integer
            Dim dmq_l_user_4 As Integer
            Dim dmq_l_user_5 As Integer
            End Structure 'dmq_user_struc t

            <StructLayout(L ayoutKind.Seque ntial)Public Structure
            dmq_user_struct _string
            <MarshalAs(Unma nagedType.ByVal Array, SizeConst:=20)D im
            dmq_user_string () As Byte

            Public Sub Initialize()
            ReDim dmq_user_string (20)
            End Sub
            End Structure 'dmq_header_as_ words

            ...
            Dim the_struct as dmq_user_struct
            Dim the_string as dmq_user_struct _string

            Comment

            • sexauthor@gmail.com

              #7
              Re: Using an array of bytes with fixedoffset in a struct?

              On Apr 19, 1:23 pm, sexaut...@gmail .com wrote:
              Bill, I could do it like that but I then would not be able to access
              that byte array easily as Integers.
              >
              It might be helpful if you were to provide the C/C++ defintions of this
              structure. It's really hard to know what your doing with out seeing the
              original :)
              >
              Ok, here is the VB6 code paraphrased by request. This is the simplest
              structure, the code has more complex ones but they all work on the
              same principle - lots of data values and then another type/struct that
              splits it by bytes or words.
              >
              Public Const dmq_s_user_data As Long = 20
              >
              Public Type dmq_user_string
              dmq_b_user_data (0 To dmq_s_user_data - 1) As Byte
              End Type 'dmq_user_strin g
              >
              Public Type dmq_user_struct
              dmq_l_user_1 As Long
              dmq_l_user_2 As Long
              dmq_l_user_3 As Long
              dmq_l_user_4 As Long
              dmq_l_user_5 As Long
              End Type 'dmq_user_struc t
              >
              Dim the_struct as dmq_user_struct
              Dim the_string As dmq_user_string
              >
              ' Fill the struct
              the_struct.dmq_ l_user_1 = 100
              the_string.dmq_ l_user_2 = 200
              the_string.dmq_ l_user_3 = 200
              the_string.dmq_ l_user_4 = 200
              the_string.dmq_ l_user_5 = 200
              ' Convert it to a string
              the_string = LSet(the_struct )
              ' Pass it as an argument to a DLL
              ...
              >
              Because I was really hurting to get this phase of the conversion
              project done last night, this is how I handled it. Clunky, but at
              least the app runs (milestone!). Note: this is not the line for line
              code, I actually managed to throw away the struct listed above and
              used this code on a different one, but I've changed the code to
              illustrate the technique.
              >
              Option Strict Off
              Option Explicit On
              Imports System.Runtime. InteropServices
              Imports System.IO
              Imports System.Runtime. Serialization.F ormatters.Binar y
              Module Conversion
              >
              Public Function RawSerialize(By Ref Anything As Object) As Byte()
              Call debug_message(8 0, "- Starting RawSerialize")
              Dim Size As Integer = Marshal.SizeOf( Anything)
              >
              Dim RawDatas() As Byte
              ReDim RawDatas(Size)
              >
              Dim Buffer As IntPtr
              Buffer = Marshal.AllocHG lobal(Size)
              >
              Marshal.Structu reToPtr(Anythin g, Buffer, False)
              Marshal.Copy(Bu ffer, RawDatas, 0, Size)
              Marshal.FreeHGl obal(Buffer)
              RawSerialize = RawDatas
              >
              Call debug_message(8 0, "- Ending RawSerialize")
              End Function
              >
              Public Function RawDeserialize( ByVal RawDatas As Byte(), ByVal
              AnyType As Type) As Object
              Call debug_message(8 0, "- Starting RawDeserialize" )
              Dim Size As Integer = Marshal.SizeOf( AnyType)
              >
              Dim Buffer As IntPtr
              Buffer = Marshal.AllocHG lobal(size)
              >
              Marshal.Copy(Ra wDatas, 0, Buffer, Size)
              RawDeserialize = Marshal.PtrToSt ructure(Buffer, AnyType)
              Marshal.FreeHGl obal(Buffer)
              >
              Call debug_message(8 0, "- Ending RawDeserialize" )
              End Function
              End Module
              >
              <StructLayout(L ayoutKind.Seque ntial)Public Structure dmq_user_struct
              Dim dmq_l_user_1 As Integer
              Dim dmq_l_user_2 As Integer
              Dim dmq_l_user_3 As Integer
              Dim dmq_l_user_4 As Integer
              Dim dmq_l_user_5 As Integer
              End Structure 'dmq_user_struc t
              >
              <StructLayout(L ayoutKind.Seque ntial)Public Structure
              dmq_user_struct _string
              <MarshalAs(Unma nagedType.ByVal Array, SizeConst:=20)D im
              dmq_user_string () As Byte
              >
              Public Sub Initialize()
              ReDim dmq_user_string (20)
              End Sub
              End Structure 'dmq_header_as_ words
              >
              ...
              Dim the_struct as dmq_user_struct
              Dim the_string as dmq_user_struct _string
              Oops the rest got cut off. Also noted above I mistyped something in
              the example way above, it should look like this:

              the_struct.dmq_ l_user_1 = 100
              the_struct.dmq_ l_user_2 = 200
              the_struct.dmq_ l_user_3 = 200
              the_struct.dmq_ l_user_4 = 200
              the_struct.dmq_ l_user_5 = 200

              ' And resuming with the new code ...
              the_string = RawDeserialize( RawSerialize(th e_struct),
              the_string.GetT ype())
              ' Now the_string has all the data from the_struct and can be
              passed to the DLL

              I'd seen code examples of this on the net but they didn't work for me
              until I played around with the exact way I defined the structs. But
              this works. I would have liked a more elegant solution though, and
              I'm worried that the serialize/deserialize code might be buggy but I
              couldn't find anything else.

              Comment

              • sexauthor@gmail.com

                #8
                Re: Using an array of bytes with fixedoffset in a struct?

                Oops the rest got cut off. Also noted above I mistyped something in
                the example way above, it should look like this:
                >
                the_struct.dmq_ l_user_1 = 100
                the_struct.dmq_ l_user_2 = 200
                the_struct.dmq_ l_user_3 = 200
                the_struct.dmq_ l_user_4 = 200
                the_struct.dmq_ l_user_5 = 200
                >
                ' And resuming with the new code ...
                the_string = RawDeserialize( RawSerialize(th e_struct),
                the_string.GetT ype())
                ' Now the_string has all the data from the_struct and can be
                passed to the DLL
                >
                I'd seen code examples of this on the net but they didn't work for me
                until I played around with the exact way I defined the structs. But
                this works. I would have liked a more elegant solution though, and
                I'm worried that the serialize/deserialize code might be buggy but I
                couldn't find anything else.
                Another typo! Just to be complete, there is of course a call to
                the_string.Init ialize()
                before you start using Serialize/Deserialize with it, otherwise it has
                the tendency to crash.

                Comment

                • Tom Shelton

                  #9
                  Re: Using an array of bytes with fixedoffset in a struct?

                  On Apr 18, 11:23 pm, sexaut...@gmail .com wrote:
                  Bill, I could do it like that but I then would not be able to access
                  that byte array easily as Integers.

                  ... sure you could. You could use System.BitConve rter to convert the
                  appropriate sections of the array.

                  Dim dmq_l_user_1 As Integer = BitConverter.To Int32
                  (astruct.dmq_b_ user_data, 0)
                  Dim dmq_l_user_2 As Integer =
                  BitConverter.To Int32(astruct.d mq_b_user_data, 4)
                  ....


                  --
                  Tom Shelton

                  Comment

                  Working...