Results 1 to 29 of 29

Thread: Length of an array of UDTs ?

  1. #1

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359

    Length of an array of UDTs ?

    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...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  2. #2
    The Devil crptcblade's Avatar
    Join Date
    Aug 2000
    Location
    Quetzalshacatenango
    Posts
    9,091
    Length = ((UBound(array)-LBound(Array)+1)*Len(UDT)

    I think
    Laugh, and the world laughs with you. Cry, and you just water down your vodka.


    Take credit, not responsibility

  3. #3
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Are the strings in the UDT variable length or fixed length?

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  4. #4

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    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...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  5. #5

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Nah won't work.

    VB Code:
    1. (UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systemInfoType)

    Says systemInfoType is not defined.
    Which is true, as its just the name I gave the UDT
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  6. #6
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    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)
    VB Code:
    1. Private Type MYTYPE
    2.     strValue As String
    3.     intValue As Integer
    4. End Type
    5. Private Sub Command1_Click()
    6. Dim myTypes(3) As MYTYPE
    7. myTypes(0).strValue = "abcdefghijklmnopqrstuvwxyz"
    8. myTypes(0).intValue = 21
    9. myTypes(1).strValue = "Visual Basic"
    10. myTypes(1).intValue = 15
    11. myTypes(2).strValue = "Good Luck"
    12. myTypes(2).intValue = 1024
    13. myTypes(3).strValue = "Jamie is a Drunkard"
    14. myTypes(3).intValue = 2054
    15.  
    16. MsgBox Len(myTypes(0))
    17. End Sub
    That will return 6 as only a pointer (Long, 4 bytes) is stored in the UDT, not the string.

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  7. #7
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    From MSDN
    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

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  8. #8

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Hmmmmm.
    How would you get the total datasize of myTypes() though ?
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  9. #9
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Looking for a alternative to a loop of the array.
    VB Code:
    1. For i = LBound(myTypes) To UBound(myTypes)
    2.     lngLength = lngLength + LenB(myTypes(i).intValue) + LenB(myTypes(i).strValue)
    3. Next i
    4. MsgBox lngLength

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  10. #10
    Frenzied Member
    Join Date
    Jul 2002
    Posts
    1,370
    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.

  11. #11

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    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
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  12. #12
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    rEPLACE:
    (UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systemInfoType)
    with:
    VB Code:
    1. (UBound(systemInfo) - LBound(systemInfo) + 1) * Len(systeminfo(LBound(systeminfo)))

    Because Len needs an instance of the variable, not it's type...
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  13. #13
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Have an idea...Give me a sec....

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  14. #14

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Originally posted by MerrionComputin
    VB Code:
    1. (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) ?
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  15. #15
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Nah! No use.

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  16. #16
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849

    Just wondering..........

    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

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  17. #17
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    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:
    1. Option Explicit
    2.  
    3. Public Property Get DataSize() As Long
    4.  
    5. End Property

    Then each class implements that i.e.:
    VB Code:
    1. 'cPrintersInfo
    2.  
    3. Implements ISerialiseable
    4.  
    5. Public Property get ISerialiseable_DataSize() As Long
    6.     ISerialiseable_DataSize = 8
    7. 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:
    1. Dim siThis As cSystemInfo
    2.  
    3. lBytesNeeded = siThis.Iserialiseable_DataSize
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  18. #18
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    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:
    1. Private Type MYTYPE
    2.     strValue As String
    3.     intValue As Integer
    4. End Type
    5.  
    6. Private Type AllTypes
    7.     udtAllTypes() As MYTYPE
    8. End Type
    9.  
    10. Private Sub Command1_Click()
    11. Dim myTypes(3) As MYTYPE, lngLength As Long, all As AllTypes
    12. Dim tmpVal As Long
    13.  
    14. myTypes(0).strValue = "abcdefghijklmnopqrstuvwxyz"
    15. myTypes(0).intValue = 21
    16. myTypes(1).strValue = "Visual Basic"
    17. myTypes(1).intValue = 15
    18. myTypes(2).strValue = "Good Luck"
    19. myTypes(2).intValue = 1024
    20. myTypes(3).strValue = "Jamie is a Drunkard"
    21. myTypes(3).intValue = 2054
    22.  
    23. all.udtAllTypes = myTypes
    24.  
    25. MsgBox all.udtAllTypes(3).strValue
    26. MsgBox Len(all)
    27.  
    28. End Sub

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  19. #19

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    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...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  20. #20
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    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.

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  21. #21

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    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...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  22. #22
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    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...
    Whats fibers?

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  23. #23
    Frenzied Member MerrionComputin's Avatar
    Join Date
    Apr 2001
    Location
    Dublin, Ireland
    Posts
    1,616
    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.
    ----8<---------------------------------------
    NEW - The .NET printer queue monitor component
    ----8<---------------------------------------
    Now with Examples of use

  24. #24

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Dunc, it sounds like a lovely idea, if I had of thought of it before I wrote nearly the entire application
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  25. #25

  26. #26

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    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....
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  27. #27
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    Jamie: Take a look here and somewhere at the end of this one there is a mention that DirectX may have a solution.

    Hope U find them useful

    Regards

    KayJay

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  28. #28
    Frenzied Member KayJay's Avatar
    Join Date
    Jul 2001
    Location
    Chennai
    Posts
    1,849
    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
    Attached Files Attached Files

    "Brothers, you asked for it."
    ...Francisco Domingo Carlos Andres Sebastian D'Anconia

  29. #29

    Thread Starter
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Thanks I'll check them out
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width