Anyone happen to know how I'd find out the length of an array of UDTs that I have ?
I need to so that I can pass a pointer and data length to a function...
Printable View
Anyone happen to know how I'd find out the length of an array of UDTs that I have ?
I need to so that I can pass a pointer and data length to a function...
Length = ((UBound(array)-LBound(Array)+1)*Len(UDT)
I think
Are the strings in the UDT variable length or fixed length?
crptcblade: I hadn't thought of that. I'll give it a go.
KayJay: The hundred of so strings that I have are all variable length :)
Its a very complex UDT...
Nah won't work.
VB Code:
(UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systemInfoType)
Says systemInfoType is not defined.
Which is true, as its just the name I gave the UDT :confused:
Length = ((UBound(array)-LBound(Array)+1)*Len(UDT)
That will not work for variable length strings and its LENB especially if its going to passed to an external DLL or function (I read Ur previous post Jamie)
That will return 6 as only a pointer (Long, 4 bytes) is stored in the UDT, not the string.VB Code:
Private Type MYTYPE strValue As String intValue As Integer End Type Private Sub Command1_Click() Dim myTypes(3) As MYTYPE myTypes(0).strValue = "abcdefghijklmnopqrstuvwxyz" myTypes(0).intValue = 21 myTypes(1).strValue = "Visual Basic" myTypes(1).intValue = 15 myTypes(2).strValue = "Good Luck" myTypes(2).intValue = 1024 myTypes(3).strValue = "Jamie is a Drunkard" myTypes(3).intValue = 2054 MsgBox Len(myTypes(0)) End Sub
From MSDN
Quote:
Remarks
One (and only one) of the two possible arguments must be specified. With user-defined types, Len returns the size as it will be written to the file.
Note Use the LenB function with byte data contained in a string, as in double-byte character set (DBCS) languages. Instead of returning the number of characters in a string, LenB returns the number of bytes used to represent that string. With user-defined types, LenB returns the in-memory size, including any padding between elements. For sample code that uses LenB, see the second example in the example topic.
Note Len may not be able to determine the actual number of storage bytes required when used with variable-length strings in user-defineddata types
Hmmmmm.
How would you get the total datasize of myTypes() though ?
Looking for a alternative to a loop of the array.
VB Code:
For i = LBound(myTypes) To UBound(myTypes) lngLength = lngLength + LenB(myTypes(i).intValue) + LenB(myTypes(i).strValue) Next i MsgBox lngLength
Since they are strings (OLECHAR or BSTR) you have to iterate thru the whole array and sum the lengths.
Except - that does not give the actual length of the UDT.
When you Dim ccc as String the actual variable is a quadword
in length. BSTR are actually string descriptors. The first longword is the address of string buffer, the second is the length.
The other problem is: VB converts all VB strings on calls to dll's to
null-terminated byte arrays (C-style char arrays). This is because most dll's are written in C and don't expect BSTR. And cannot deal with them either.
You are better off copying your UDT array into something else, another UDT array with fixed length byte arrays that you can quantify correctly.
I have a code module in VB, and the only thing in it is just the UDT declaration.
The module is 10k.
There are hundreds of variable length strings, arrays of other UDTs, booleans, longs etc.
So the looping option would be an absolute nightmare :eek:
rEPLACE:
with:Quote:
(UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systemInfoType)
VB Code:
(UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systeminfo(LBound(systeminfo)))
Because Len needs an instance of the variable, not it's type...
Have an idea...Give me a sec....:)
Quote:
Originally posted by MerrionComputin
VB Code:
(UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systeminfo(LBound(systeminfo)))
Because Len needs an instance of the variable, not it's type...
I had that idea, but imagine this situation :
The array : systemInfo(0).hardwareInfo.PrintersInfo()
On systemInfo(0), that computer may have no printers, so that array is empty.
But on systemInfo(1), that computer might have 10 printers, so that array would be dimensioned.
So surely the datasize of systemInfo(0) would differ greatly to that of systemInfo(1) ?
Nah! No use. :o :(
How often would U need to calculate the length of the array of the UDT.
If its only a one-off or very rarely, dump it to disk and read the filelength. A dirty hack but it should work:o
This is why arrays and UDTs are so out of favour.
Collectiosn and classes is where it's at.
You could have an interface class ISerialiseable that is like:
VB Code:
Option Explicit Public Property Get DataSize() As Long End Property
Then each class implements that i.e.:
VB Code:
'cPrintersInfo Implements ISerialiseable Public Property get ISerialiseable_DataSize() As Long ISerialiseable_DataSize = 8 End property
And if a class includes a collection the it's implementation of ISerialiseable_DataSize iterates the collection getting their sizes and adding them to its.
Therefore your eventual code is:
VB Code:
Dim siThis As cSystemInfo lBytesNeeded = siThis.Iserialiseable_DataSize
MerrionComputin, very true.
But to see if things can be managed as is...................
The code below shows the length of the second UDT as 4. I presume its 'cause a pointer to the actual data is stored in the UDT. Would it be possible to get that pointer (do a memcopy) and read 4 bytes before that pointer to extract the length? I ask this as I understand that VB stores the length in memory as a "long" just before the begining of the actual data. At least that is the case with storage of variable length Strings in VB.
VB Code:
Private Type MYTYPE strValue As String intValue As Integer End Type Private Type AllTypes udtAllTypes() As MYTYPE End Type Private Sub Command1_Click() Dim myTypes(3) As MYTYPE, lngLength As Long, all As AllTypes Dim tmpVal As Long myTypes(0).strValue = "abcdefghijklmnopqrstuvwxyz" myTypes(0).intValue = 21 myTypes(1).strValue = "Visual Basic" myTypes(1).intValue = 15 myTypes(2).strValue = "Good Luck" myTypes(2).intValue = 1024 myTypes(3).strValue = "Jamie is a Drunkard" myTypes(3).intValue = 2054 all.udtAllTypes = myTypes MsgBox all.udtAllTypes(3).strValue MsgBox Len(all) End Sub
I've tried pulling the 4 bytes before the start of the first element of the udt in memory, but that doesnt seem to return anything interesting...
Same luck here :( . Should it not be an array of UDTs, it should be manageable even with variable length strings in a UDT. An array holds just one more set of pointers rather than any contiguous data.
Guess, U'll have to change Ur approach or do a disk dump.
Well ill use a disk dump for development.
But i would much rather have a better implementation when the product goes live :(
... maybe I could use fibers...
Whats fibers? :confused:Quote:
Originally posted by plenderj
Well ill use a disk dump for development.
But i would much rather have a better implementation when the product goes live :(
... maybe I could use fibers...
Anything non fixed length in a UDT has to be implemented by a pointer. Fixed length stuff is just held in a contiguous memory block.
So - with alltypes, the value in VarPtr(alltypes) is a pointer to the first MYTYPE. This in turn holds a pointer to a string (4 bytes) folowed by the integer itself (2 bytes) followed by the next one and so on.
You would be far better to go the classes / collections route IMO - you can even pass them between apps.
Dunc, it sounds like a lovely idea, if I had of thought of it before I wrote nearly the entire application ;)
The length of a UDT is NOT Len(udtMyUDT)
It is in fact LenB(udtMyUDT)/2
:D
Woka
But what I need to find, as another solution to the problem I've been having, is the total size in memory that the array of udts takes up.
Well I'm assuming an array of information occupies a contiguous block of memory....
Also see if U could use the VBHELP32.DLL (attached). It had been used earlier to solve this issue, and there is a reference to handling arrays and variable length string in its help file.
I tried it with the code I posted above, but can't get it work. Hope U do.
Regards
KayJay
Thanks I'll check them out :)