Two Structures, Same Data

  • Thread starter Thread starter Dennis Woos
  • Start date Start date
D

Dennis Woos

I am trying to get two structures to map the same data, like a union.
Having failed to get the FieldOffset attribute to work at runtime, I tried:

----------------------------------------------------------------
Option Strict On

Imports System

Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _

Public Structure Struct1

<VBFixedString(6), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=6)> _

Public f1 As String

End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _

Public Structure Struct2

<VBFixedString(1), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _

Public f1 As String

<VBFixedString(2), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _

Public f2 As String

<VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _

Public f3 As String

End Structure



Module Module1

Sub Main()

Dim s1 As Struct1

s1.f1 = "ABCDEF"

Console.WriteLine(s1.f1 + " " + (Marshal.SizeOf(s1)).ToString)

Dim ptrStruct As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(s1))

Try

Marshal.StructureToPtr(s1, ptrStruct, False)

Dim s2 As Struct2

s2 = CType(Marshal.PtrToStructure(ptrStruct, GetType(Struct2)), Struct2)

Console.WriteLine(s2.f1 + "," + s2.f2 + "," + s2.f3 + " " +
(Marshal.SizeOf(s2)).ToString)

Console.ReadLine()

Finally

Marshal.FreeHGlobal(ptrStruct)

End Try

End Sub

End Module

----------------------------------------------------------------

The first Console.Writeline outputs 'ABCDEF 6', and the second ',B,DE 6'
instead of 'A,BC,DEF 6'. Clearly, I am losing the first byte of each
string in Struct2. Any help? Thanks.

Dennis
 
I am trying to get two structures to map the same data, like a union.
Having failed to get the FieldOffset attribute to work at runtime, I tried:

----------------------------------------------------------------
Option Strict On

Imports System

Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _

Public Structure Struct1

<VBFixedString(6), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=6)> _

Public f1 As String

End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=1)> _

Public Structure Struct2

<VBFixedString(1), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _

Public f1 As String

<VBFixedString(2), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _

Public f2 As String

<VBFixedString(3), MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _

Public f3 As String

End Structure



Module Module1

Sub Main()

Dim s1 As Struct1

s1.f1 = "ABCDEF"

Console.WriteLine(s1.f1 + " " + (Marshal.SizeOf(s1)).ToString)

Dim ptrStruct As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(s1))

Try

Marshal.StructureToPtr(s1, ptrStruct, False)

Dim s2 As Struct2

s2 = CType(Marshal.PtrToStructure(ptrStruct, GetType(Struct2)),
Struct2)

Console.WriteLine(s2.f1 + "," + s2.f2 + "," + s2.f3 + " " +
(Marshal.SizeOf(s2)).ToString)

Console.ReadLine()

Finally

Marshal.FreeHGlobal(ptrStruct)

End Try

End Sub

End Module

----------------------------------------------------------------

The first Console.Writeline outputs 'ABCDEF 6', and the second ',B,DE 6'
instead of 'A,BC,DEF 6'. Clearly, I am losing the first byte of each
string in Struct2. Any help? Thanks.

I solved this by:
1) Option Strict Off
2) replaced VBFixedString with VBFixedArray and adjusted upper bounds
3) replaced ByValTStr with ByValArray
4) replaced strings in structures with char()

The strings were being marshalled with a null terminator.

Dennis
 
Back
Top