By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,290 Members | 1,666 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,290 IT Pros & Developers. It's quick & easy.

Struct trouble Visual Basic.net

P: n/a
Hi there !!!

I browsed around the Internet in search for a solution of a little difficult
problem i have in VB.NET....

However, i cannot find a suitable anwser anywhere, so i thought i'll give it
a try here...

Okay, here's the deal:
I am trying to read from unmanaged memory with a class type struct, this
works fine as i can read the data from the unmanaged memory. The trouble
starts when i try to fill an array of structs within a struct, all the array
members get filled with the last read values from the unmanaged memory:

The structs i build for managing the unmanaged memory;
<code>
Imports System.Runtime.InteropServices

'Beckhoff TwinCat Struct

'TYPE ST_TeleMeBool :
'STRUCT
' ID:STRING;
' Value:BOOL;
' Qualify:STRING;
' TypeB:STRING;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TeleMeBool
'-- enum unmanagedtype ByValStr = a fixed size string of 80 chars
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public ID As String = ""
<MarshalAs(UnmanagedType.I1)> _
Public Value As Boolean
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public Qualify As String = ""
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public TypeB As String = ""

End Class
'Beckhoff TwinCat Struct

'TYPE ST_TelemeReal :
'STRUCT
' ID:STRING;
' Value:REAL;
' Qualify:STRING;
' TypeB:STRING;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TeleMeReal

<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public ID As String = ""
'-- enum unmanagedtype r4 = a 4 byte Real (aka Single / system.float)
<MarshalAs(UnmanagedType.R4)> _
Public Value As Single
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public Qualify As String = ""
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public TypeB As String = ""

End Class
'Beckhoff TwinCat Struct

'TYPE ST_TelemeOut :
'STRUCT
' CountBool:INT;
' CountReal:INT;
' bArray: ARRAY[0..999] OF ST_TelemeBool;
' rArray: ARRAY[0..999] OF ST_TelemeReal;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TelemeOut

'-- enum unmanagedtype I2 = a 2 byte signed integer (aka short /
system.int16)
<MarshalAs(UnmanagedType.I2)> _
Public CountBool As Integer
<MarshalAs(UnmanagedType.I2)> _
Public CountReal As Integer
'-- enum unmanagedtype ByValArray = an array of which the maximum
elementsize MUST be specified (sizeconst)
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=999)> _
Public bArray(1000) As ST_TeleMeBool
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=999)> _
Public rArray(1000) As ST_TeleMeReal

End Class
</code>
Now the code to read the unmanaged code and fill my struct:

<code>

Public stTelemeOut As ST_TelemeOut = New ST_TelemeOut '--
declares a VB side St_TelemeOut struct to fill from PLC TelemeOut struct

Public stTelemeBool As ST_TeleMeBool = New ST_TeleMeBool '-- vb
sided instance of a single .bArray() struct element within St_TelemeOut, may
be useful

Public stTelemeReal As ST_TeleMeReal = New ST_TeleMeReal

For i = 0 To .CountBool - 1
stTelemeBool.ID = ADSClient.ReadAny(hbID(i),
GetType(String), New Integer() {80}) '--
WATCH SYNTAX TO ASK STRINGS!!!!
stTelemeBool.Value = ADSClient.ReadAny(hbValue(i),
GetType(Boolean))
stTelemeBool.Qualify = ADSClient.ReadAny(hbQualify(i),
GetType(String), New Integer() {80})
stTelemeBool.TypeB = ADSClient.ReadAny(hbTypeB(i),
GetType(String), New Integer() {80})
.bArray(i) = stTelemeBool
Next i
For i = 0 To .CountReal - 1
stTelemeReal.ID = ADSClient.ReadAny(hrID(i),
GetType(String), New Integer() {80})
stTelemeReal.Value = ADSClient.ReadAny(hrValue(i),
GetType(Single))
stTelemeReal.Qualify = ADSClient.ReadAny(hrQualify(i),
GetType(String), New Integer() {80})
stTelemeReal.TypeB = ADSClient.ReadAny(hrTypeB(i),
GetType(String), New Integer() {80})
.rArray(i) = stTelemeReal
Next i
</code>

The problem i encounter resides in the statement:
bArray(i) = stTelemeBool

and (equally so):

rArray(i) = stTelemeReal

ALL the array members get filled with the last read data values from the
unmanaged memory, this instead of filling each array member with the
corresponding unamanaged memory data.

I am at a loss... can anybody help me out??
Nov 21 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Couple of questions here
when i = 0 and you check the value of hbID is it the same when i=ubound(i)
if that is the case then your hb object is not getting declared or populated
correct
if they are not the same then take a look at
since your not rediming your arrays then that could be reason.. All though
never seen that to be a problem but
redim array(ubound(.countreal))
before you start looping to fill your array

you do not show us how hb is getting filled
If the other component is filling hb.. When you get hb back make sure it is
more then array of 1

"DaHool" <Da****@discussions.microsoft.com> wrote in message
news:F0**********************************@microsof t.com...
Hi there !!!

I browsed around the Internet in search for a solution of a little
difficult
problem i have in VB.NET....

However, i cannot find a suitable anwser anywhere, so i thought i'll give
it
a try here...

Okay, here's the deal:
I am trying to read from unmanaged memory with a class type struct, this
works fine as i can read the data from the unmanaged memory. The trouble
starts when i try to fill an array of structs within a struct, all the
array
members get filled with the last read values from the unmanaged memory:

The structs i build for managing the unmanaged memory;
<code>
Imports System.Runtime.InteropServices

'Beckhoff TwinCat Struct

'TYPE ST_TeleMeBool :
'STRUCT
' ID:STRING;
' Value:BOOL;
' Qualify:STRING;
' TypeB:STRING;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TeleMeBool
'-- enum unmanagedtype ByValStr = a fixed size string of 80 chars
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public ID As String = ""
<MarshalAs(UnmanagedType.I1)> _
Public Value As Boolean
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public Qualify As String = ""
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public TypeB As String = ""

End Class
'Beckhoff TwinCat Struct

'TYPE ST_TelemeReal :
'STRUCT
' ID:STRING;
' Value:REAL;
' Qualify:STRING;
' TypeB:STRING;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TeleMeReal

<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public ID As String = ""
'-- enum unmanagedtype r4 = a 4 byte Real (aka Single / system.float)
<MarshalAs(UnmanagedType.R4)> _
Public Value As Single
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public Qualify As String = ""
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
Public TypeB As String = ""

End Class
'Beckhoff TwinCat Struct

'TYPE ST_TelemeOut :
'STRUCT
' CountBool:INT;
' CountReal:INT;
' bArray: ARRAY[0..999] OF ST_TelemeBool;
' rArray: ARRAY[0..999] OF ST_TelemeReal;
'END_STRUCT
'END_TYPE

<StructLayout(LayoutKind.Sequential, pack:=1)> _
Public Class ST_TelemeOut

'-- enum unmanagedtype I2 = a 2 byte signed integer (aka short /
system.int16)
<MarshalAs(UnmanagedType.I2)> _
Public CountBool As Integer
<MarshalAs(UnmanagedType.I2)> _
Public CountReal As Integer
'-- enum unmanagedtype ByValArray = an array of which the maximum
elementsize MUST be specified (sizeconst)
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=999)> _
Public bArray(1000) As ST_TeleMeBool
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=999)> _
Public rArray(1000) As ST_TeleMeReal

End Class
</code>
Now the code to read the unmanaged code and fill my struct:

<code>

Public stTelemeOut As ST_TelemeOut = New ST_TelemeOut '--
declares a VB side St_TelemeOut struct to fill from PLC TelemeOut struct

Public stTelemeBool As ST_TeleMeBool = New ST_TeleMeBool '-- vb
sided instance of a single .bArray() struct element within St_TelemeOut,
may
be useful

Public stTelemeReal As ST_TeleMeReal = New ST_TeleMeReal

For i = 0 To .CountBool - 1
stTelemeBool.ID = ADSClient.ReadAny(hbID(i),
GetType(String), New Integer() {80}) '--
WATCH SYNTAX TO ASK STRINGS!!!!
stTelemeBool.Value = ADSClient.ReadAny(hbValue(i),
GetType(Boolean))
stTelemeBool.Qualify = ADSClient.ReadAny(hbQualify(i),
GetType(String), New Integer() {80})
stTelemeBool.TypeB = ADSClient.ReadAny(hbTypeB(i),
GetType(String), New Integer() {80})
.bArray(i) = stTelemeBool
Next i
For i = 0 To .CountReal - 1
stTelemeReal.ID = ADSClient.ReadAny(hrID(i),
GetType(String), New Integer() {80})
stTelemeReal.Value = ADSClient.ReadAny(hrValue(i),
GetType(Single))
stTelemeReal.Qualify = ADSClient.ReadAny(hrQualify(i),
GetType(String), New Integer() {80})
stTelemeReal.TypeB = ADSClient.ReadAny(hrTypeB(i),
GetType(String), New Integer() {80})
.rArray(i) = stTelemeReal
Next i
</code>

The problem i encounter resides in the statement:
bArray(i) = stTelemeBool

and (equally so):

rArray(i) = stTelemeReal

ALL the array members get filled with the last read data values from the
unmanaged memory, this instead of filling each array member with the
corresponding unamanaged memory data.

I am at a loss... can anybody help me out??

Nov 21 '05 #2

P: n/a
> starts when i try to fill an array of structs within a struct, all
the array
members get filled with the last read values from the unmanaged memory:

The problem is that you reuse the same instance of the object every
time through the loop. Your rArray was filled with references to the
*SAME* object. You need to create a NEW object each time inside the
for loops, like this:
Public stTelemeBool As ST_TeleMeBool
Public stTelemeReal As ST_TeleMeReal

For i = 0 To .CountBool - 1 stTelemeBool = New ST_TelemeOut 'CREATE A NEW OBJECT
HERE

'Code to set stTelemeBool properties
.bArray(i) = stTelemeBool
Next i
For i = 0 To .CountReal - 1 stTelemeReal = New ST_TeleMeReal 'CREATE A NEW OBJECT
HERE

'Code to set stTelemeReal properties
.rArray(i) = stTelemeReal
Next i
</code>


Once you create the objects inside the for loops you should be ok

Nov 21 '05 #3

P: n/a
that is not the problem if you look at the code below he
makes stTelemeReal = the array at the end of the loop
So does not matter if he resues the stTelemeReal
over and over in his loops

"Chris Dunaway" <du******@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
starts when i try to fill an array of structs within a struct, all

the array
members get filled with the last read values from the unmanaged

memory:

The problem is that you reuse the same instance of the object every
time through the loop. Your rArray was filled with references to the
*SAME* object. You need to create a NEW object each time inside the
for loops, like this:
Public stTelemeBool As ST_TeleMeBool
Public stTelemeReal As ST_TeleMeReal

For i = 0 To .CountBool - 1

stTelemeBool = New ST_TelemeOut 'CREATE A NEW OBJECT
HERE

'Code to set stTelemeBool properties
.bArray(i) = stTelemeBool
Next i
For i = 0 To .CountReal - 1

stTelemeReal = New ST_TeleMeReal 'CREATE A NEW OBJECT
HERE

'Code to set stTelemeReal properties
.rArray(i) = stTelemeReal
Next i
</code>


Once you create the objects inside the for loops you should be ok

Nov 21 '05 #4

P: n/a
It does matter, when he assigns the object reference to the array in
this line
.rArray(i) = stTelemeReal


He now has two refereneces *to the same object*. At the end of the
loop, *all* the array elements point to the same object. And since
there is only one object, they all reflect the values of the most
recent changes.

Had he defined his "structs" as Structures instead of classes it may be
different, since he would then be working with value types and not
reference types.

Chris

Nov 21 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.