-
Apr 18th, 2018, 03:22 AM
#1
Thread Starter
Member
Dynamic change of a structure length inside a function
Example declarations:
Code:
Private Type SUB_STRUCTURE
SubMember1(15) As Byte
SubMember2 As LARGE_INTEGER
SubMember3 As LARGE_INTEGER
SubMember4 As Long
End Type
Private Type STRUCTURE
Member1 As Long
Member2 As Long
Member3 As SUB_STRUCTURE
PadMember4 As Long
' static array size
Member5(287) As Byte
End Type
In a function:
Dim test As STRUCTURE
MsgBox Len(test) ' it's "336" here
For a specific DeviceIO-ControlCode I want to call, this length may be too small and causes an ERROR_INSUFFICIENT_BUFFER ("ErrNr. 122).
So, i'm in need to redim Member5 dynamically in a way that length of variable "test" (length of STRUCTURE) also changes.
I tried to declare the structure as follows:
Code:
Private Type STRUCTURE
Member1 As Long
Member2 As Long
Member3 As SUB_STRUCTURE
PadMember4 As Long
Member5() As Byte
End Type
In a function:
Dim test As STRUCTURE
MsgBox Len(test) ' it's "52" here
ReDim test.Member5(287)
MsgBox Len(test) ' still obviously "52" but should become at least 336
I hope my problem was explained in a sufficient way.
Thanks for any reply.
-
Apr 18th, 2018, 06:45 AM
#2
Re: Dynamic change of a structure length inside a function
Unfortunately, VB6 does not support variable-length structures. The typical workaround for this is to just simply make the structure as large as possible. However, keep in mind that VB6 limits UDTs to just 64 KB, so if the API needs more buffer space, you'll have to resort to other means (e.g., String, Byte array or your own allocated memory).
-
Apr 18th, 2018, 07:08 AM
#3
Re: Dynamic change of a structure length inside a function
At least three options I can think of right off
1. As mentioned by Victor Bravo VI, oversize the member structure
2. Use a byte array, but get a bit creative and test well...
Edited: Approach below only works well if the last member is to be dynamic
Code:
Private Type STRUCTURE
Member1 As Long
Member2 As Long
Member3 As SUB_STRUCTURE
PadMember4 As Long
' static array size
Member5(287) As Byte
End Type
' /////////// Air-Code follows for test function
' dynamically sized, add another 1024 bytes to the final member
Dim bStructure() As Byte, lSize As Long
Dim uUDT As STRUCTURE
' fill in the structure then
lSize = LenB(uUDT)
ReDim bStructure(0 To lSize + 1023) ' add another 1024 bytes
CopyMemory bStructure(0), uUDT, lSize
' pass to the API the address of bStructure(0)
' now if needed, you can copy from the byte array back to your uUDT variable, but only lSize in bytes
' uUDT.Member5 will still be 288 bytes. But from that member's memory address there are actually 288+1024 bytes
' don't know if Member5 is string data or something else. If string data, it is doable to extract just those 288+1024 bytes to a string
3. Create multiple versions of your structure. Many that use GDI are accustomed to this when declaring BitmapInfo and OSVersion structures
Last edited by LaVolpe; Apr 18th, 2018 at 07:18 AM.
-
Apr 18th, 2018, 09:33 AM
#4
Re: Dynamic change of a structure length inside a function
Also, Zphere, you should get into the habit of using LenB() with your UDTs rather than Len(). They will often return the same thing. However, when they don't, you almost always want the value that LenB() returns rather than the value for Len(). There are a couple of different reasons they may be different, but I won't go into them here.
And yeah, VB6 UDTs are rather completely resolved when compiled by VB6, which means there's no "dynamic" way to change their size. However, you've been given excellent work-arounds.
Good Luck,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 18th, 2018, 10:38 AM
#5
Thread Starter
Member
Re: Dynamic change of a structure length inside a function
At first, a big thanks to all of you
(In hope my english is good enough...)
Victor Bravo VI:
Clear answer to my initial problem (as it was posted). Thanks also for the reference.
To be honest, at least I don't need this structure because I was able to read out all information by dimming a byte array with desired (or needed) size and passed this to the specific IOCTL-Function.
Via Do...Loop While lRet = 0 And Err.LastDllError = 122 I simply resized the byte array before passing it again to the IOCTL-function.
By looping through the byte array data, I've been able to find all offsets and length for each of the members from the data structure shown in my example.
I was just curious and wanted to know if I could extract all info by declaring a structure in the declaration area of a module or a cls that can be resized.
LaVolpe:
I can follow your code of option 2 and it seems very clever to me.
Indeed, we're talking about the last member only. But, the byte array contains not only string data.
Moreover, numeric values must be extracted of datatype Long, Double or largeInteger.
Option 3 sounds somehow funky - it would never came into my mind till you mentioned it. I'm curious to try this option.
Elroy:
Thanks for mention the Len/LenB issue ..behaviour changed
After reading your suggestions, no use of a declared structure but usage of a byte array (as described above) dimmed inside a function seems to be the best choice.?
Drawback is that I need sub-functions or subs to retrieve the appropriate byte sequences of this array and to convert data into the appropriate data type.
Last edited by Zphere; Apr 20th, 2018 at 12:35 AM.
-
Apr 18th, 2018, 01:25 PM
#6
Re: Dynamic change of a structure length inside a function
Originally Posted by Zphere
By looping through the byte array data, I've been able to find all offsets and length for each of the members from the data structure shown in my example.
. . .
Drawback is that I need sub-functions or subs to retrieve the appropriate byte sequences of this array and to convert data into the appropriate data type.
There are a number of techniques that you can utilize to typecast your Byte array to any desired UDT. LaVolpe showed one such approach and here's another one. This method uses the CallWindowProc API function to perform typecasting (you could also use the DispCallFunc API if you want to do it in an Object module [.FRM, .CLS, .CTL, etc.]). The advantages of this technique are reduced memory usage and possibly faster execution especially when the structure is large.
Code:
Option Explicit 'In a standard (.BAS) module
Private Declare Function CallWindowProcW Lib "user32.dll" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Type UDT
cbSize As Long
Buffer As Byte
End Type
Private Sub Foo()
Dim Buffer(0& To &HFFFF&) As Byte
'This will cast the Buffer() Byte array to a UDT structure. Pass the buffer size as well.
CallWindowProcW AddressOf Bar, VarPtr(Buffer(0&)), &H10000, 0&, 0&
End Sub
Private Function Bar(ByRef U As UDT, ByVal BufferSize As Long, ByVal Reserved1 As Long, ByVal Reserved2 As Long) As Long
'The parameter U now occupies the same memory as the Buffer() variable in Sub Foo()
'Any changes in U's members will be reflected in the Buffer() variable and vice versa
U.cbSize = BufferSize
'Call the API here and pass the UDT
End Function
EDIT
Another possible solution that you could try is the SAFEARRAY method where you manipulate an array so that its elements overlays arbitrary memory locations.
Last edited by Victor Bravo VI; Apr 18th, 2018 at 02:50 PM.
-
Apr 18th, 2018, 01:55 PM
#7
Re: Dynamic change of a structure length inside a function
Hi Zphere,
I suppose I'll say a bit more. After re-reading your initial post, I see that you tried to use a dynamic array in your UDT (structure). There are certain things that, when placed in a UDT, only place a four-byte address in the UDT. The most obvious examples are Objects, variable length (BSTR) Strings, and Dynamic Arrays. In other words, for any kind of device I/O, these aren't going to work. That was your initial problem.
I'm assuming that the size of this UDT (structure) is determined by certain fields in its header. If it were me, I'd use a Byte array, just as you apparently have.
And then, I'd start using CopyMemory to move it into a UDT that was more convenient for me. In fact, if done correctly, after the data is read into your byte array, you could then use Dynamic Arrays. Here's an API declaration for it:
Code:
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef destination As Any, ByRef source As Any, ByVal length As Long)
Be sure to notice that destination is first, and then source.
Let's say we'd like to move 8 bytes, starting at bb(12) of your Byte array, and you'd like to move this into a variable named SomeIeeeDouble. We could do something like the following:
Code:
CopyMemory SomeIeeeDouble, bb(12), 8
Using those ideas, we could read our byte array, snoop around in it to figure out how large the Dynamic Array should be in our UDT, dimension this Dynamic Array, and then use the first (or whatever) element of this dynamic array as a destination (using some spot in our byte array as a source).
Maybe that'll help.
Elroy
EDIT1: Just as a further FYI, there's no problem using the specific elements of a UDT as either the source or destination for CopyMemory. Or even specific elements within an array. Or both.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 18th, 2018, 03:43 PM
#8
Thread Starter
Member
Re: Dynamic change of a structure length inside a function
Very, very interesting Victor Bravo VI.
This is new to me, I will test this.
I'm shifting away from my initial question I know,
but at first I would like to refer to Elroys approach.
Elroy, let's say I initialised an array to a sufficient size.
CLS: declaration area
Code:
Option Explicit
' Yes, in real I already use a UDT
private Type UDTSub
subMember1 As string
subMember2 As string
subMember3 As string
end type
Private Type UDT
Member1 As string
Member2 As string
Member3 As string
Member4 as string
subMembers () as UDTSub
End Type
private DD as UDT
In a function:
Code:
Friend Function Test() as Boolean
Redim DD(0): Redim DD(0).subMembers(0)
' in this example the array is oversized and assumes! a needed length
Dim DATA(18479) as byte
' DeviceHandle is known
If DevIOCTL( _
HDev, ANY_IOCTL_CONTROL_CODE, _
ByVal 0&, 0&, ByVal VarPtr(DATA(0)), _
Ubound(DATA), 0&, ByVal 0&) = 0 _
Then
' error handling here
Else
Test=True
' To retrieve data from the 1st and 2nd Member
' (both of long if a structure would be used - see my initial example)
' I use the following "universal" function to pass values directly to my UDT
With DD(0)
.Member1 = BytesToNumEx(Data, 0, 3)
.Member2 = BytesToNumEx(Data, 4, 7)
...
End With
EndIf
End Function
Private Function BytesToNumEx(ByteArray() As Byte, StartRec As Long, EndRec As Long, Optional UnSigned As Boolean) As Double
' All credits to the Author: Imran Zaheer - http://www.freevbcode.com/ShowCode.asp?ID=1006
Dim i As Integer
Dim lng256 As Double
Dim lngReturn As Double
On Error GoTo ExFkt
lng256 = 1
lngReturn = 0
If EndRec < 1 Then EndRec = UBound(ByteArray)
If StartRec > EndRec Or StartRec < 0 Then GoTo ExFkt
lngReturn = lngReturn + (ByteArray(StartRec))
For i = (StartRec + 1) To EndRec
lng256 = lng256 * 256
If i < EndRec Then
lngReturn = lngReturn + (ByteArray(i) * lng256)
Else
' if -ve
If ByteArray(i) > 127 And UnSigned = False Then
lngReturn = (lngReturn + ((ByteArray(i) - 256) * lng256))
Else
lngReturn = lngReturn + (ByteArray(i) * lng256)
End If
End If
Next i
BytesToNumEx = lngReturn
Exit Function
ExFkt:
BytesToNumEx = -1
Err.Clear
End Function
I'm not familar with CopyMemory. Where could it come into play here?
Regarding your "tip", am I understanding right that here CopyMemory helps to copy a byte sequence
into memory that will be available by the OutVariable (first parameter)?
If so, I could replace the first parts of BytesToNumEx (setting the byte array sequence)
with CopyMemory.?
Last edited by Zphere; Apr 20th, 2018 at 12:37 AM.
-
Apr 18th, 2018, 04:11 PM
#9
Re: Dynamic change of a structure length inside a function
Hi Zphere,
Ok, first, recognize that those strings in your UDTs are also only going to be memory-address-pointers. The strings themselves are actually not in the UDT.
Rather than try and sort out what you're doing, let me mock up a little example of what I'm talking about. When I get it mocked up, I'll post it as another post.
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 18th, 2018, 05:12 PM
#10
Re: Dynamic change of a structure length inside a function
Here we go.
This stuff can get involved, especially appreciating that VB6 stores strings as Unicode. I assumed any incoming string would be ASCII.
Here's just an example. To test, throw it into Form1, and play. The MakeRandomDataStream is just a mock-up of some data with a known (but variable length) structure.
Code:
Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef destination As Any, ByRef source As Any, ByVal length As Long)
'
' Ok, for grins, I've assumed we have incoming data of variable length.
' However, we know that it has a certain structure:
' First, it will have a Long data #1 length, with the data representing a string(ASCII).
' The ASCII String data will follow the length.
' Next, it will have a Long data #2 length, with the data representing Bytes.
' The Byte data will follow the length.
' Next, it will just have two values at the end, one a Double and the second a Long.
'
' We'll also assume the whole thing is never longer than 1000 bytes (actually less).
'
Private Type MyUdtType
Data1Len As Long
MyString As String
Data2Len As Long
MyBytes() As Byte
MyValue3 As Double
MyValue4 As Long
End Type
'
Private Sub Form_Load()
GetParseAndShowData
End Sub
Private Sub Form_Click()
GetParseAndShowData
End Sub
Private Sub GetParseAndShowData()
Dim bbIn() As Byte ' This will be my input data stream.
Dim bbTemp() As Byte
bbIn = MakeRandomDataStream
'
' Now, let's parse our data and make it "pretty".
Dim MyUdt As MyUdtType
'
' The string length (ASCII) and the string.
CopyMemory MyUdt.Data1Len, bbIn(1), 4 ' Get the string length.
ReDim bbTemp(1 To MyUdt.Data1Len)
CopyMemory bbTemp(1), bbIn(1 + 4), MyUdt.Data1Len ' Get string into bbTemp.
MyUdt.MyString = StrConv(bbTemp, vbUnicode) ' Make a Unicode VB6 string.
'
' The bytes length and the bytes.
CopyMemory MyUdt.Data2Len, bbIn(1 + 4 + MyUdt.Data1Len), 4 ' Get the Bytes length.
ReDim MyUdt.MyBytes(1 To MyUdt.Data2Len) ' Make bytes space.
CopyMemory MyUdt.MyBytes(1), bbIn(1 + 4 + MyUdt.Data1Len + 4), MyUdt.Data2Len ' Get bytes.
'
' And finally the last two values.
CopyMemory MyUdt.MyValue3, bbIn(1 + 4 + MyUdt.Data1Len + 4 + MyUdt.Data2Len), 8
CopyMemory MyUdt.MyValue4, bbIn(1 + 4 + MyUdt.Data1Len + 4 + MyUdt.Data2Len + 8), 4
'
' And let's see what we got.
Debug.Print "------------------------------"
Debug.Print MyUdt.Data1Len, MyUdt.MyString
Debug.Print MyUdt.Data2Len, StrConv(MyUdt.MyBytes, vbUnicode) ' Convert the bytes to Unicode for printing.
Debug.Print MyUdt.MyValue3
Debug.Print MyUdt.MyValue4
Debug.Print "------------------------------"
End Sub
Private Function MakeRandomDataStream() As Byte()
Dim i1 As Long
Dim i2 As Long
Dim j As Long
Dim bbData1() As Byte
Dim bbData2() As Byte
Dim bbOut() As Byte
Dim Value3 As Double
Dim Value4 As Long
'
Randomize
'
' Some random string.
' But let's keep it simple and assume they're ASCII characters.
i1 = Int(Rnd * 100 + 1) ' A number between 1 and 100.
ReDim bbData1(1 To i1)
For j = 1 To i1
bbData1(j) = Int(26 * Rnd + 65) ' ASCII values for letters between A and Z.
Next j
'
' This time, some random collection of bytes, seen as bytes.
i2 = Int(Rnd * 100 + 1) ' A number between 1 and 100.
ReDim bbData2(1 To i2)
For j = 1 To i2
bbData2(j) = Int(26 * Rnd + 65) ' ASCII values for letters between A and Z.
Next j
'
' Make last two values.
Value3 = Rnd * 10000# + 1# ' Some value between 1 and 10000.
Value4 = Int(Rnd * 10000@ + 1@) ' Some integer (Long) between 1 and 10000.
'
' And now we'll use CopyMemory to shove it into our Random Data Stream.
' Zphere, I assume you will be reading this from some other source.
'
ReDim bbOut(1 To (4 + i1 + 4 + i2 + 8 + 4)) ' Long, String[i1,ASCII], Long, Bytes[i2], Double, Long.
'
CopyMemory bbOut(1), i1, 4 ' Length of string.
CopyMemory bbOut(1 + 4), bbData1(1), i1 ' The ASCII string.
CopyMemory bbOut(1 + 4 + i1), i2, 4 ' Length of bytes.
CopyMemory bbOut(1 + 4 + i1 + 4), bbData2(1), i2 ' The bytes.
CopyMemory bbOut(1 + 4 + i1 + 4 + i2), Value3, 8 ' First value at end.
CopyMemory bbOut(1 + 4 + i1 + 4 + i2 + 8), Value4, 4 ' Second value at end.
MakeRandomDataStream = bbOut
End Function
Enjoy,
Elroy
EDIT1: If I were actually doing this for production, I'd probably make a pointer into bbIn() that kept track of where we were, rather than just letting the expression get longer and longer.
EDIT2: It was bugging me so I added a lBufPtr (buffer pointer):
Code:
Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef destination As Any, ByRef source As Any, ByVal length As Long)
'
' Ok, for grins, I've assumed we have incoming data of variable length.
' However, we know that it has a certain structure:
' First, it will have a Long data #1 length, with the data representing a string(ASCII).
' The ASCII String data will follow the length.
' Next, it will have a Long data #2 length, with the data representing Bytes.
' The Byte data will follow the length.
' Next, it will just have two values at the end, one a Double and the second a Long.
'
' We'll also assume the whole thing is never longer than 1000 bytes (actually less).
'
Private Type MyUdtType
Data1Len As Long
MyString As String
Data2Len As Long
MyBytes() As Byte
MyValue3 As Double
MyValue4 As Long
End Type
'
Private Sub Form_Load()
GetParseAndShowData
End Sub
Private Sub Form_Click()
GetParseAndShowData
End Sub
Private Sub GetParseAndShowData()
Dim bbIn() As Byte ' This will be my input data stream.
Dim bbTemp() As Byte
Dim lBufPtr As Long
bbIn = MakeRandomDataStream
'
' Now, let's parse our data and make it "pretty".
Dim MyUdt As MyUdtType
lBufPtr = 1 ' Start buffer pointer.
'
' The string length (ASCII) and the string.
CopyMemory MyUdt.Data1Len, bbIn(lBufPtr), 4 ' Get the string length.
lBufPtr = lBufPtr + 4 ' Move buffer pointer.
ReDim bbTemp(1 To MyUdt.Data1Len)
CopyMemory bbTemp(1), bbIn(lBufPtr), MyUdt.Data1Len ' Get string into bbTemp.
lBufPtr = lBufPtr + MyUdt.Data1Len ' Move buffer pointer.
MyUdt.MyString = StrConv(bbTemp, vbUnicode) ' Make a Unicode VB6 string.
'
' The bytes length and the bytes.
CopyMemory MyUdt.Data2Len, bbIn(lBufPtr), 4 ' Get the Bytes length.
lBufPtr = lBufPtr + 4 ' Move buffer pointer.
ReDim MyUdt.MyBytes(1 To MyUdt.Data2Len) ' Make bytes space.
CopyMemory MyUdt.MyBytes(1), bbIn(lBufPtr), MyUdt.Data2Len ' Get bytes.
lBufPtr = lBufPtr + MyUdt.Data2Len ' Move buffer pointer.
'
' And finally the last two values.
CopyMemory MyUdt.MyValue3, bbIn(lBufPtr), 8
lBufPtr = lBufPtr + 8 ' Move buffer pointer.
CopyMemory MyUdt.MyValue4, bbIn(lBufPtr), 4
lBufPtr = lBufPtr + 4 ' No need for this one, but hey ho.
'
' And let's see what we got.
Debug.Print "------------------------------"
Debug.Print MyUdt.Data1Len, MyUdt.MyString
Debug.Print MyUdt.Data2Len, StrConv(MyUdt.MyBytes, vbUnicode) ' Convert the bytes to Unicode for printing.
Debug.Print MyUdt.MyValue3
Debug.Print MyUdt.MyValue4
Debug.Print "------------------------------"
End Sub
Private Function MakeRandomDataStream() As Byte()
Dim i1 As Long
Dim i2 As Long
Dim j As Long
Dim bbData1() As Byte
Dim bbData2() As Byte
Dim bbOut() As Byte
Dim Value3 As Double
Dim Value4 As Long
'
Randomize
'
' Some random string.
' But let's keep it simple and assume they're ASCII characters.
i1 = Int(Rnd * 100 + 1) ' A number between 1 and 100.
ReDim bbData1(1 To i1)
For j = 1 To i1
bbData1(j) = Int(26 * Rnd + 65) ' ASCII values for letters between A and Z.
Next j
'
' This time, some random collection of bytes, seen as bytes.
i2 = Int(Rnd * 100 + 1) ' A number between 1 and 100.
ReDim bbData2(1 To i2)
For j = 1 To i2
bbData2(j) = Int(26 * Rnd + 65) ' ASCII values for letters between A and Z.
Next j
'
' Make last two values.
Value3 = Rnd * 10000# + 1# ' Some value between 1 and 10000.
Value4 = Int(Rnd * 10000@ + 1@) ' Some integer (Long) between 1 and 10000.
'
' And now we'll use CopyMemory to shove it into our Random Data Stream.
' Zphere, I assume you will be reading this from some other source.
'
ReDim bbOut(1 To (4 + i1 + 4 + i2 + 8 + 4)) ' Long, String[i1,ASCII], Long, Bytes[i2], Double, Long.
'
CopyMemory bbOut(1), i1, 4 ' Length of string.
CopyMemory bbOut(1 + 4), bbData1(1), i1 ' The ASCII string.
CopyMemory bbOut(1 + 4 + i1), i2, 4 ' Length of bytes.
CopyMemory bbOut(1 + 4 + i1 + 4), bbData2(1), i2 ' The bytes.
CopyMemory bbOut(1 + 4 + i1 + 4 + i2), Value3, 8 ' First value at end.
CopyMemory bbOut(1 + 4 + i1 + 4 + i2 + 8), Value4, 4 ' Second value at end.
MakeRandomDataStream = bbOut
End Function
Last edited by Elroy; Apr 18th, 2018 at 05:23 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 19th, 2018, 11:38 AM
#11
Thread Starter
Member
Re: Dynamic change of a structure length inside a function
Elroy, thank you very much for "coaching" me here.
"Secretely", methods of byte array handling was also what I'm looking for.
I'm just changing my code regarding your suggestions and till now everything works as expected.
Although not needed for my tasks, also thanks for your instructions on how to create a byte array with specific data types using CopyMemory.
I learned much here.
Anyway, in time I would although like to try the methods Victor Bravo VI described.
Therefore, I won't mark this thread as resolved (I'm "somehow" convinced that questions will appear).
-
Apr 19th, 2018, 11:58 AM
#12
Re: Dynamic change of a structure length inside a function
using a typelib and an Array Map, you never end up allocating the memory for subMembers.
You do have to watch out for access violations though, as VB assumes it's a large fixed size.
Code:
private Type DDSub
subMember1 As string
subMember2 As string
subMember3 As string
end type
Private Type UDT
Member1 As string
Member2 As string
Member3 As string
Count as Long
subMembers (&HFFFF&) as UDTSub
End Type
Dim MyUDT() As UDT
With AryMap(RefAry(MyUDT), pData)
With MyUDT(0)
Dim I&
For I = 0 To .Count - 1
Debug.Print .subMembers(I).subMember1
Next
End With
End With
-
Apr 19th, 2018, 12:34 PM
#13
Re: Dynamic change of a structure length inside a function
Also, Zphere, once you get the hang of CopyMemory, it's not too bad. Also, you'll eventually need to use it with "ByVal VarPtr()", but that's sort of another discussion.
But, as a big caveat, just always make sure you understand what memory you're copying. If you ever try to copy memory that's not memory you're tracking, you'll rather quickly crash the VB6 IDE (and/or your compiled program). That's one reason to save often when you're developing code with CopyMemory so, if you do crash, you don't lose your work.
Once you get it all running, and only copying memory that you understand, all should work extremely well.
Good Luck,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 19th, 2018, 04:38 PM
#14
Thread Starter
Member
Re: Dynamic change of a structure length inside a function
Also, thanks for your warnings.
Am I allowed to ask what "memory" one might try to copy is not memory?
Could you/someone recommend a good reference about how CopyMemory works?
DEXWERX, I think I understand what you were trying to say but I'm not able to follow your code.
From which specific typelib are you talking about? And what about the AryMap function?
Would it be presuming to ask for more specific explainations?
Last edited by Zphere; Apr 19th, 2018 at 04:42 PM.
-
Apr 19th, 2018, 05:17 PM
#15
Re: Dynamic change of a structure length inside a function
Well, it's probably copying TO memory that you shouldn't as opposed to copying FROM memory that you shouldn't. However, Windows keeps pretty tight control over all of memory these days. If you're copying into/out-of your own variables, there should never be a problem.
Here's the Microsoft MSDN page on the API call, but I'm not sure that's much help. Basically, when you pass any numeric variable, just pass it ByRef. When you pass VarPtr(SomeVariable), pass it ByVal. In terms of the actual call, the memory addresses to copy (along with the bytes to copy) must be on the stack. Strings get a bit more complicated, but that's not because of CopyMemory. That's just more to do with how VB6 deals with Strings.
Good Luck,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Apr 19th, 2018, 10:06 PM
#16
Re: Dynamic change of a structure length inside a function
Originally Posted by Zphere
Anyway, in time I would although like to try the methods Victor Bravo VI described.
The methods DEXWERX and I are proposing are simply strategies for avoidance of data duplication (i.e., the copying of memory back and forth between the UDT and the Byte array). Why would you want to avoid data duplication? Well, there are at least two good reasons. The primary reason is, if you're the type of programmer who's mindful of your program's memory footprint, you would obviously want to reduce instances of the same data to the bare minimum, especially if it's taking quite a lot of space. The secondary reason is, copying bytes back and forth will definitely take some time (compared to simply making a variable point to the same memory occupied by another variable), again especially if there's a lot of data.
People might argue that there is little benefit to be gained from using these kinds of strategies. Well, that's mostly true. However, it is also true that C/C++ programs tends to be a bit faster and more frugal in memory usage than VB6 programs. This is partly because the C/C++ language has cast operators (the reinterpret_cast in particular) that makes it easy to change the interpretation of one data type to another data type, thus avoiding unnecessary copying. VB6 has no such built-in capability, but various workarounds have been devised to help make up for this deficiency.
Zphere, would it be possible for you to show your actual code? Seeing the actual code will enable us to give you better recommendations. Thank you.
-
Apr 20th, 2018, 12:34 AM
#17
Thread Starter
Member
Re: Dynamic change of a structure length inside a function
Elroy, I think I now understand your statement of going sure that destination should be the first parameter.
Regarding your link: habitually, RTFM is the first thing I do. This was the first side I visited.
I've been in hope that somebody could provide a better reference.
Nevermind, it's time for checking and experimenting now - thanks for everything.
Victor Bravo VI, sure - but not now.
I see, I've written working but somehow clumpsy code (2 years ago) that can be optimised by quite simple instructions from Elroy.
Please give me some time to completely rewrite it before posting.
I'm really interested in the thingies you stated and help from experts is always great.
Please keep in mind, that I'm doing all this stuff in my rare sparetime (for fun and relaxation), so it may takes a little while.
Am I allowed to drop you a pm?
-
Apr 20th, 2018, 12:38 PM
#18
Re: Dynamic change of a structure length inside a function
Originally Posted by Zphere
Am I allowed to drop you a pm?
Sure, go ahead.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|