How can I serialize a UDT into a byte array...I tried CopyMemory, but that also copies the padding bytes. I need universal code so that I supply any UDT and a byte array is returned...any ideas...thanks.
Last edited by Martin Wilson; May 31st, 2002 at 11:25 AM.
Everything I have found suggests saving the udt to a file and then loading it into a byte array...which is what I was doing before. Are there any other methods?
Originally posted by Martin Wilson How can I serialize a UDT into a byte array...I tried CopyMemory, but that also copies the padding bytes. I need universal code so that I supply any UDT and a byte array is returned...any ideas...thanks.
What does your UDT look like? I send large (6000+ bytes) UDTs to C and COBOL servers with no problems.
We do a lot of inter-program communication and the programs are written in various languages (C, COBOL, TAL, VC++, VB) so we generally standardize the interprocess messages to look like COBOL records. Also, because different platforms allocate different sizes for certain data types, we stick to Integers, Longs and fixed length Strings.
When I want a UDT within a UDT, I use a fixed length String as a place holder and CopyMemory the internal UDT into the String.
For example:
VB Code:
Public Type dclStdHeader ' current length = 52
ttl_len As Long ' long ttl_len;
msgtype As Long ' long msgtype;
orig_id As Long ' long orig_id;
seq_num As Long ' long seq_num;
tran_type As Long ' long tran_type;
curr_wndw As Long ' long curr_wndw;
curr_req As Integer ' short curr_req
user_def As String * 26 ' char user_def[26];
End Type
Public Type dclTypeStatus ' current length = 124
name As String * 8 ' char pname[8];
custid As String * 8 ' char cust[8];
svrclass As String * 16 ' char svrclass[16];
pthway As String * 16 ' char pthway[16];
errtime As String * 20 ' char errdate[20];
state As String * 12 ' char state[12];
lasterr As String * 6 ' char lasterr[6];
proctype As String * 6 ' short proctype[6];
restarts As String * 4 ' char restarts[4];
monitorname As String * 8 ' char monitorname[8];
errordesc As String * 20 ' char errordesc[20];
End Type
Public Type dclStatusRep
rep_hdr As String * 52 ' holder for dclStdHeader
repid As Integer ' short rtncode;
system As Integer ' short system;
index As Integer ' short index;
lines As Integer ' short linecnt;
statline(giMaxLines) As String * 124 ' holders for dclTypeStatus
End Type
Records of type dclStatusRep are returned from a C program - the equivalent C struct fields are listed in the comments to the right.
rep_hdr is a holder for the header UDT and statline is an array of (50) holders for the status record UDTs.
This file demonstrate the problem...compare the 2 files produced.
The problems occurs because in memory, longs need to start on a 4 byte boundary, but as the UDT starts with an integer, 2 padding bytes need to be added. Instead of IILLLL, you get IIPPLLLL.
Last edited by Martin Wilson; May 31st, 2002 at 10:33 AM.
[Highlight=VB]
Private Type Person
Name As String * 30
Age As Integer
Sex As String * 1
MaritalStatus As String * 10
End Type
Private Type Car
Make As String * 30
Model As String * 30
Color As String * 10
End Type
Private Type Marks
Math As Integer
English As Integer
Physics As Integer
Geography As Integer
Biology As Integer
Chemistry As Integer
History As Integer
End Type
Private Type CarSummaryType
Buffer As String * 70
End Type
Private Type PersonSummaryType
Buffer As String * 42
End Type
Private Type MarksSummaryType
Buffer As String * 7
End Type
Dim MySelf As Person
Dim MyCar As Car
Dim MyMarks As Marks
Dim MyCarSummary As CarSummaryType
Dim MySelfSummary As PersonSummaryType
Dim MyMarksSummary As MarksSummaryType
Private Sub GetValuesForMarks(Buffer As String)
Dim udtDetails As Marks
Dim udtSummary As MarksSummaryType
udtSummary.Buffer = Buffer
LSet udtDetails = udtSummary
With udtDetails
Debug.Print .Biology
Debug.Print .Chemistry
End With
End Sub
[Highlight=VB]
with the above u could pass the "BUFFER" as string over winsock and then use something like the "GETVALUES....." sub-routine to reconctruct the data at the other end.
"Brothers, you asked for it."
...Francisco Domingo Carlos Andres Sebastian D'Anconia
That is what I was doing before and it does work...but I want to get rid of the file access and send the UDT more directly. The file access seems pointless and slows the code down.
You cannot (that I know of) serialize a UDT without creating a compress/expand routine.
In .net and java you can as you can base your class on the serialization object.
Heres my sugesstion, turn then UDT into a class.
Create a function inside that serialises it, and also that expands it. And just call the functions, you can also make it return a byte array etc, or exactly how you want it formated.
Then I would need a seperate class for each UDT. There must be a way as the udt is stored correctly when saved to a file...does anyone know where I can the source to vb functions?
Well, there a few terms for serialization, but heres the one thats being discussed.
You have a data structure, which holds certain data.
When you serialize the structure, you convert the data into a stream. You can then send / save the data, and then later on un-serialize it back into its original form.
A very good use is saving EXACTLY all the variables and there states in a class, and as such you can load them back up again with no problem. Imagin if you save serialized data to disk every 5 seconds, and then your PC crashes. You can just load up the last set of data back into the class, and it will act exactly how you left it.
In this case, the strucuture is a picture, and the struture wants to be serialized so it can be sent across IP to another computer, that can then expand it back out.
Not sure if this would work but I used this to move stuff among COM servers...
Try using LSet and defining a second UDT that has the same byte length as the UDT you're trying to pass.
Code:
Public udtMyType
Name as string * 30
City as string * 20
End Type
Public udtMyTypeSerialized
Buffer as string *50
End Type
Public udtData as udtMyType
Public udtBuffer as udtMyTypeSerialized
With udtData
.Name = "Achichincle"
.City = "San Diego"
End with
LSet udtBuffer = udtData
Now udtBuffer is essentially a byte-array in memory of all your data so you should be able to CopyMemory it as needed.
When you get it to where you want it just do the LSet in reverse...
That still requires me to know the elements of the UDT...it would be easier to just add the elements individually. It looks like I gonna have to give up on solving this.
That was a tough one to crack!! Played with CopyMem, CopyMemByPtr, VarPtr, PropBags. Nah! stumped me.
Here it goes. VB 6 Not Possible!!!!. VB.Net Possible
Workaround for VB 6. Get yourself the "VBHLP32.DLL" from http://www.softcircuits.com and then use the attachment. Your Byte Array is as required! You still have to add another parmeter(s) apart from the UDT though.
Had fun though! 2 days with nothing to do, I was getting mad
"Brothers, you asked for it."
...Francisco Domingo Carlos Andres Sebastian D'Anconia
Thanks a lot KayJay That is great...I still need to provide pszFields but I can cope with that. How did you find it...just searched google?
Thanks a lot