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.
Printable View
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's a UDT?
User Definite Type.
User Defined TypeQuote:
Originally posted by skald2k
User Definite Type.
Ah! so you have a User Defined Type something on the order of:
and you want to run it through a function to return a binary stringCode:Define Person
Name as Text
Dbay as Date
SSN as Text
....
suitable for saving and then re-loading at a future time.
Is this the gist of the question?
And you want it to work with ANY UDT that you can come up with
in the future?
You've sort of got it...basically I want to send graphics headers through winsock.
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?
What does your UDT look like? I send large (6000+ bytes) UDTs to C and COBOL servers with no problems.Quote:
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.
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:
Records of type dclStatusRep are returned from a C program - the equivalent C struct fields are listed in the comments to the right.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
rep_hdr is a holder for the header UDT and statline is an array of (50) holders for the status record UDTs.
HTH
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.
Use LSET.
[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 Command1_Click()
MySelf.Age = 24
MySelf.MaritalStatus = "Single"
MySelf.Name = "KayJay"
MySelf.Sex = "M"
MyCar.Make = "Mercedez Benz"
MyCar.Model = "C-Class Saloon"
MyCar.Color = "Raven"
MyMarks.Biology = 80
MyMarks.Chemistry = 90
MyMarks.English = 70
MyMarks.Geography = 85
MyMarks.History = 75
MyMarks.Math = 95
MyMarks.Physics = 80
LSet MyCarSummary = MyCar
LSet MySelfSummary = MySelf
LSet MyMarksSummary = MyMarks
MsgBox MyCarSummary.Buffer
MsgBox MySelfSummary.Buffer
GetValuesForMarks MyMarksSummary.Buffer
End Sub
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.
The other end is a webbrowser so I can't control how it does it unfortunately.
Does this help?
No :( You are just re-declaring the UDT...the data needs to be sent by winsock...which doesn't accept UDTs.
Since LEN and LENB are giving problems:(
The attachment?
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.
i.e
VB Code:
'MyClass Private strString as String Private intInteger as Integer Public funcCompressMe() as String funcCompressMe = strstring & "MY$PLIT" & intInteger & "MY$PLIT" End Function Public Sub procExpandMe(Data as String) dim strData() as String strData = Split(Data,"MY$PLIT") strString = strData(0) intInteger = Int(Val(strData(1)) End Sub
Its just a quick demo, but I use something similar for my project atm. But more advanced version.
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?
How do you store it now ? Give some example code.
what does Serialize mean?
JAT.
If we use property bags, would it take the same amount of effort as for creating a Class?
Say something like : -
VB Code:
Private Type BITMAPFILEHEADER bfType As Integer bfSize As Long bfReserved1 As Integer bfReserved2 As Integer bfOffBits As Long End Type Private Sub Command1_Click() Dim FileHeader As BITMAPFILEHEADER FileHeader.bfType = &H4D42 FileHeader.bfOffBits = Len(FileHeader) + CLng(40) FileHeader.bfSize = Len(FileHeader) + CLng(40 + 100) Open "C:\windows.000\desktop\UDT.txt" For Binary As #1 Put #1, , FileHeader Close #1 Dim propbag As New PropertyBag Dim propArray() As Byte Dim thearray() As Byte propbag.WriteProperty "bfType", &H4D42 propbag.WriteProperty "bfOffBits", Len(FileHeader) + CLng(40) propbag.WriteProperty "bfSize", Len(FileHeader) + CLng(40 + 100) propArray() = propbag.Contents End End Sub
You could then parse the resultant Byte array and strip them off the inherent PropBag data which should be fixed in lengths. JAT
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.
All I want to send are image headers to a web browser followed by the image data.
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.
Now udtBuffer is essentially a byte-array in memory of all your data so you should be able to CopyMemory it as needed.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
When you get it to where you want it just do the LSet in reverse...
It was in a book I read...
Achichincle, thats been suggested before and he does not want to do that, since he has no conrol over the client App.
The closest I could manage to serialize a UDT is, as I mentioned using PropertyBags.
I picked some really cool stuff on the net, forget where. Its great.
You could (see attachment) do a "FOR EACH...NEXT" with UDT's as properties of a PropertyBag. Thats the closest.
Check it out Martin and see if it could of any use to u.
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.
Good Luck.
Just asking... If the purpose is to send an image file to a webrowser, why not just use HTTP command? "HTTP /GET...." or what ever the syntax is.
Are you building the images from code?
It is sort of an HTTP server, it generates an image depending on the url it recieves and sends it to the browser. That works fine.
PHEW!!!!!!!:D
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:D
KayJay - sorry, I don't know how I missed your post. Gotta start drinking coffe again... :rolleyes:
Thanks a lot KayJay :D 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 :)
Yeah!! Google and Google and Google and Google.......
Umpteen searches with various keywords and finally:D :)
But learnt a helluva a lot in the process. Especially the undocumented function VartPtr and its derivatives.
Can u belive that CopyMemByPtr returned only three results from Google & Yahoo & only ONE from Teoma.
And more, all those point to the same enumeration example of AllAPI Guide. No help at all:mad:
Stumbled somehow on that site.
Well anyway Good Luck with your app.
Achichincle, Coffee sounds good. I'll have some myself:)
well solved