Home |
Search |
Today's Posts |
#1
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
I have a data structure consisting of an array of User Defined Types (UDF) - called Udta say. Each Udta contains 4 members that are also UDT's - called Udtb say. I wrote a function to return a pointer to a specific Udtb. But to my surprise, the pointer creates a new instance of Udtb although it inherits from the Udtb I was trying to point to.
I have confirmed this behaviour by monitoring the variables in Local Window.. I also display the pointer values using VarPtr. My question. Is it possible to get a pointer to a specific Udtb as I am trying to do. It seems to me that I want 2 pointers pointing at the same UDF. I would prefer to stay with UDT's and not use classes. The code is vba in Excel 2010. Thank you |
#2
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
Am 17.05.2018 um 15:01 schrieb Desmond Walsh:
I have a data structure consisting of an array of User Defined Types (UDF) - called Udta say. Each Udta contains 4 members that are also UDT's - called Udtb say. I wrote a function to return a pointer to a specific Udtb. But to my surprise, the pointer creates a new instance of Udtb although it inherits from the Udtb I was trying to point to. I have confirmed this behaviour by monitoring the variables in Local Window. I also display the pointer values using VarPtr. My question. Is it possible to get a pointer to a specific Udtb as I am trying to do. It seems to me that I want 2 pointers pointing at the same UDF. I would prefer to stay with UDT's and not use classes. The code is vba in Excel 2010. Here you will find some detailed information about vba pointers: https://bytecomb.com/vba-internals-a...ters-in-depth/ https://communities.bentley.com/prod...roperty-values Therefore i would prefer objects instead udts andÂ* and pass them by reference. Ulrich |
#3
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
On Thursday, May 17, 2018 at 10:03:03 AM UTC-4, Ulrich Möller wrote:
Am 17.05.2018 um 15:01 schrieb Desmond Walsh: I have a data structure consisting of an array of User Defined Types (UDF) - called Udta say. Each Udta contains 4 members that are also UDT's - called Udtb say. I wrote a function to return a pointer to a specific Udtb. But to my surprise, the pointer creates a new instance of Udtb although it inherits from the Udtb I was trying to point to. I have confirmed this behaviour by monitoring the variables in Local Window. I also display the pointer values using VarPtr. My question. Is it possible to get a pointer to a specific Udtb as I am trying to do. It seems to me that I want 2 pointers pointing at the same UDF. I would prefer to stay with UDT's and not use classes. The code is vba in Excel 2010. Here you will find some detailed information about vba pointers: https://bytecomb.com/vba-internals-a...ters-in-depth/ https://communities.bentley.com/prod...roperty-values Therefore i would prefer objects instead udts andÂ* and pass them by reference. Ulrich Thank you for the links. I am now convinced that a UDT design cannot easily support what I was trying to do. I converted my Utdb to a class. My GetPointer function returns a Variant which I change to a class pointer in the calling procedure. Everything now works as I intended. I will post some sample code illustrating the UTD problem and the simple conversion to a class based solution Desmond |
#4
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
Am 18.05.2018 um 13:28 schrieb Desmond Walsh:
On Thursday, May 17, 2018 at 10:03:03 AM UTC-4, Ulrich Möller wrote: Am 17.05.2018 um 15:01 schrieb Desmond Walsh: I have a data structure consisting of an array of User Defined Types (UDF) - called Udta say. Each Udta contains 4 members that are also UDT's - called Udtb say. I wrote a function to return a pointer to a specific Udtb. But to my surprise, the pointer creates a new instance of Udtb although it inherits from the Udtb I was trying to point to. I have confirmed this behaviour by monitoring the variables in Local Window. I also display the pointer values using VarPtr. My question. Is it possible to get a pointer to a specific Udtb as I am trying to do. It seems to me that I want 2 pointers pointing at the same UDF. I would prefer to stay with UDT's and not use classes. The code is vba in Excel 2010. Here you will find some detailed information about vba pointers: https://bytecomb.com/vba-internals-a...ters-in-depth/ https://communities.bentley.com/prod...roperty-values Therefore i would prefer objects instead udts andÂ* and pass them by reference. Ulrich Thank you for the links. I am now convinced that a UDT design cannot easily support what I was trying to do. I converted my Utdb to a class. My GetPointer function returns a Variant which I change to a class pointer in the calling procedure. Everything now works as I intended. I will post some sample code illustrating the UTD problem and the simple conversion to a class based solution Another helpful link may be https://www.vitoshacademy.com/vba-at...gh-end-in-vba/ The interesting thing is how to create a static class in vba Ulrich |
#5
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
As I mentioned in my second post, switching the member UDT (UDTb) to a class (Classb) was very simple and gave me the pointer that I wanted
Here is test code that I wrote to illustrate the problem ; -------------------------------------------------- ================================================== ================================================== ==================== Name: Module1 ================================================== ================================================== ==================== Option Explicit ' Module 1 TestUdtClass ' ' Test code to demonstrate a difference between a User Defined Type(UDT) and a Class ' '------------------------------------------------------------------------------------------- Public Type Udtb bmember1 As Integer bmember2 As Integer End Type Public Type Udta_v1 ' Some members are references to other UDT's index As Integer amember1 As Udtb amember2 As Udtb End Type Public Type Udta_v2 ' Identical to Udta_v1 with UDT members replaced by Class members index As Integer amember1 As Classb amember2 As Classb End Type Public Sub UsingUdt() ' ' Attempting to get a pointer to a UDT one layer down in the data structure ' The data structure is an array of UDT's with some members also UDT's (different UDT) Dim marray() As Udta_v1 Dim udtb_pointer As Udtb ReDim marray(1 To 2) As Udta_v1 Debug.Print vbNewLine & "USINGUDT Data structures use UDT's only" marray(2).index = 2 marray(2).amember1.bmember1 = 111 marray(2).amember1.bmember2 = 122 udtb_pointer = GetUdtPointer(2, marray) ' ' Display contents of Udtb Debug.Print "USINGUDT Using marray bmember1: " & marray(2).amember1.bmember1 Debug.Print "USINGUDT Using marray bmember2: " & marray(2).amember1.bmember2 Debug.Print vbNewLine Debug.Print "USINGUDT Using GetUdtPointer bmember1: " & udtb_pointer.bmember1 Debug.Print "USINGUDT Using GetUdtPointer bmember2: " & udtb_pointer.bmember2 End Sub Public Function GetUdtPointer(i As Integer, marray() As Udta_v1) As Udtb ' Intent was to get a pointer to a specific Udta. But the debug statements clearly show that ' a new instance of Udtb was created which inherited data from the targetted Utdb ' The function GetClassPointer is equivalent code for the Udta_v2 data structure ' NOTE: Use Local Window in debug mode to see the data structures being updated GetUdtPointer = marray(2).amember1 ' ' Now have two Udt pointers. Add some data GetUdtPointer.bmember2 = 277 marray(2).amember1.bmember2 = 299 ' ' Display contents of Udtb Debug.Print "GETUDTPOINTER Using marray Varptr: " & VarPtr(marray(2).amember1) Debug.Print "GETUDTPOINTER Using marray bmember2: " & marray(2).amember1.bmember1 Debug.Print "GETUDTPOINTER Using marray bmember2: " & marray(2).amember1.bmember2 Debug.Print vbNewLine Debug.Print "GETUDTPOINTER Using GetUdtPointer Varptr: " & VarPtr(GetUdtPointer) Debug.Print "GETUDTPOINTER Using GetUdtPointer bmember2: " & GetUdtPointer.bmember1 Debug.Print "GETUDTPOINTER Using GetUdtPointer bmember2: " & GetUdtPointer.bmember2 Debug.Print vbNewLine End Function Public Sub UsingClass() ' ' Attempting to get a pointer to second layer elements in the data structure ' The data structure is an array of UDT's with some members defined as instances of a class (Classb) Dim marray() As Udta_v2 Dim classb_pointer As Classb ReDim marray(1 To 2) As Udta_v2 Debug.Print vbNewLine & "USINGCLASS Data structures use UDT's and Classes" marray(2).index = 2 ' ' Because we are now using classes, must first create a class instance Set marray(2).amember1 = New Classb marray(2).amember1.bmember1 = 111 Set marray(2).amember2 = New Classb marray(2).amember1.bmember2 = 122 Set classb_pointer = GetClassPointer(2, marray) ' ' Display contents of Udtb Debug.Print "USINGCLASS Using marray bmember1: " & marray(2).amember1.bmember1 Debug.Print "USINGCLASS Using marray bmember2: " & marray(2).amember1.bmember2 Debug.Print vbNewLine Debug.Print "USINGCLASS Using GetClassPointer bmember1: " & classb_pointer.bmember1 Debug.Print "USINGCLASS Using GetClassPointer bmember2: " & classb_pointer.bmember2 End Sub Public Function GetClassPointer(i As Integer, marray() As Udta_v2) As Variant ' ' This code is identical to GetUdtPointer except for ' 1 Function name is GetClassPointer instead of GetUdtPointer ' 2 Marray defined as Udta_v2 instead of Udta_v1 ' 3 Use Set keyword to define new pointer ' 4 Function returns a Variant ' NOTE: Use Local Window in debug mode to see the data structures being updated Set GetClassPointer = marray(2).amember1 ' ' Now have two pointers. Add some data GetClassPointer.bmember2 = 277 marray(2).amember1.bmember2 = 299 ' ' Display contents of Udtb Debug.Print "GETCLASSPOINTER Using marray Objptr: " & ObjPtr(marray(2).amember1) Debug.Print "GETCLASSPOINTER Using marray Varptr: " & VarPtr(marray(2).amember1) Debug.Print "GETCLASSPOINTER Using marray bmember2: " & marray(2).amember1.bmember1 Debug.Print "GETCLASSPOINTER Using marray bmember2: " & marray(2).amember1.bmember2 Debug.Print vbNewLine Debug.Print "GETCLASSPOINTER Using GetClassPointer Objptr: " & ObjPtr(GetClassPointer) Debug.Print "GETCLASSPOINTER Using GetClassPointer Varptr: " & VarPtr(GetClassPointer) Debug.Print "GETCLASSPOINTER Using GetClassPointer bmember2: " & GetClassPointer.bmember1 Debug.Print "GETCLASSPOINTER Using GetClassPointer bmember2: " & GetClassPointer.bmember2 Debug.Print vbNewLine End Function ================================================== ================================================== ==================== Name: Classb ================================================== ================================================== ==================== ' Class Classb ' ' The members of this class are identical to the UDT Udtb ' No methods are defined for this class ' '------------------------------------------------------------------------------------------- Public bmember1 As Integer Public bmember2 As Integer ----------------------------------------------------------- Here is the output ; USINGUDT Data structures use UDT's only GETUDTPOINTER Using marray Varptr: 2152204 GETUDTPOINTER Using marray bmember2: 111 GETUDTPOINTER Using marray bmember2: 299 GETUDTPOINTER Using GetUdtPointer Varptr: 112225048 GETUDTPOINTER Using GetUdtPointer bmember2: 111 GETUDTPOINTER Using GetUdtPointer bmember2: 277 USINGUDT Using marray bmember1: 111 USINGUDT Using marray bmember2: 299 USINGUDT Using GetUdtPointer bmember1: 111 USINGUDT Using GetUdtPointer bmember2: 277 USINGCLASS Data structures use UDT's and Classes GETCLASSPOINTER Using marray Objptr: 162841984 GETCLASSPOINTER Using marray Varptr: 138064736 GETCLASSPOINTER Using marray bmember2: 111 GETCLASSPOINTER Using marray bmember2: 299 GETCLASSPOINTER Using GetClassPointer Objptr: 162841984 GETCLASSPOINTER Using GetClassPointer Varptr: 112225000 GETCLASSPOINTER Using GetClassPointer bmember2: 111 GETCLASSPOINTER Using GetClassPointer bmember2: 299 USINGCLASS Using marray bmember1: 111 USINGCLASS Using marray bmember2: 299 USINGCLASS Using GetClassPointer bmember1: 111 USINGCLASS Using GetClassPointer bmember2: 299 ------------------------------------------------------------------------ Meeting this kind of problem is intimidating. Excel cannot detect that this coding is not what the author intended. Only a close examination of the data will reveal unintended behaviour. |
#6
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
"Desmond Walsh" wrote in message
===================== I have a data structure consisting of an array of User Defined Types (UDF) - called Udta say. Each Udta contains 4 members that are also UDT's - called Udtb say. I wrote a function to return a pointer to a specific Udtb. But to my surprise, the pointer creates a new instance of Udtb although it inherits from the Udtb I was trying to point to. I have confirmed this behaviour by monitoring the variables in Local Window. I also display the pointer values using VarPtr. My question. Is it possible to get a pointer to a specific Udtb as I am trying to do. It seems to me that I want 2 pointers pointing at the same UDF. I would prefer to stay with UDT's and not use classes. The code is vba in Excel 2010. ======================= I know it's been a while since you posted but I don't follow what you are trying to do or what the problem is. You say your function to return the pointer to a particular Udtb creates a new instance of your Udtb and a new pointer. Looking at the code you posted later that's because you assign the Udtb passed to the function as the return value of the function. That creates a copy of the Udtb which will indeed have a new pointer Your code, where GetUdtPointer is the function name declared as Udtb and marray(2).amember1 (passed to the function) is also a Udtb - GetUdtPointer = marray(2).amember1 that's like doing myUDT2 = myUDT1, makes a distinct copy When the function returns and you assign the function return to a different variable, the contents will be copied into this variable which will have yet another different pointer, then the copy and pointer assigned to the function will fall out of scope. Peter T |
#7
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
On Friday, May 25, 2018 at 4:34:39 AM UTC-4, Peter T wrote:
"Desmond Walsh" wrote in message In my test code (in GetUdtPointer), I changed the value of the bmember2 property first using the pointer marray(2).amember1.bmember2 and then using the pointer GetUdtPointer.bmember2. Locals Window clearly showed 2 distinct UDTb's being updated in the scope of GetUdtPointer. This led me to believe that I could not return a pointer to a specific UDTb. But, when I switched to a class definition of UDTb, I got the pointer I wanted. Maybe I am missing a point. Could you modify the GetUdtPointer code to return a pointer to a specific UDTb. That is all I was trying to do. |
#8
Posted to microsoft.public.excel.programming
|
|||
|
|||
Problem getting a pointer to a User Defined Type (UDT)
"Desmond Walsh" wrote in message On Friday, May 25, 2018 at 4:34:39 AM UTC-4, Peter T wrote: "Desmond Walsh" wrote in message In my test code (in GetUdtPointer), I changed the value of the bmember2 property first using the pointer marray(2).amember1.bmember2 and then using the pointer GetUdtPointer.bmember2. Locals Window clearly showed 2 distinct UDTb's being updated in the scope of GetUdtPointer. This led me to believe that I could not return a pointer to a specific UDTb. But, when I switched to a class definition of UDTb, I got the pointer I wanted. Maybe I am missing a point. Could you modify the GetUdtPointer code to return a pointer to a specific UDTb. That is all I was trying to do. ============== I think you're missing the point about pointers! Rather than explain maybe this illustrates using your UDTs - ' ' normal module Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _ ByRef Destination As Any, _ ByRef Source As Any, _ ByVal Length As Long) ' this API needs adapting for use in 64bit Excel Public Type Udtb bmember1 As Integer ' 2 bytes bmember2 As Integer ' 2 bytes End Type ' total 4 bytes Public Type Udta_v1 index As Integer 'bytes 1 to 2 amember1 As Udtb 'bytes 3 to 6 amember2 As Udtb 'bytes 7 to 10 End Type ' total 10 bytes Sub test() Dim bigU As Udta_v1, ba() As Byte, i As Long bigU.index = 1 bigU.amember1.bmember1 = 2 bigU.amember1.bmember2 = 3 bigU.amember2.bmember1 = 4 bigU.amember2.bmember2 = 5 foo bigU, ba Debug.Print bigU.amember1.bmember1 ' 5623 Debug.Print bigU.amember1.bmember2 ' 8223 Debug.Print bigU.amember2.bmember1 ' 10793 Debug.Print bigU.amember2.bmember2 ' 13363 For i = 0 To UBound(ba) Debug.Print ba(i); Next ' 1 2 21 22 31 32 41 42 51 52 End Sub Sub foo(bigU As Udta_v1, ba() As Byte) Dim uB1 As Udtb, n As Integer bigU.index = 1 + 256 * 2 uB1.bmember1 = 21 + 256 * 22 ' 5623 uB1.bmember2 = 31 + 256 * 32 ' 8223 n = 41 + 256 * 42 ' 10793 CopyMemory ByVal VarPtr(bigU) + 2, uB1, 4 CopyMemory ByVal VarPtr(bigU) + 6, n, 2 CopyMemory ByVal VarPtr(bigU) + 8, (51 + 256 * 52), 2 ReDim ba(0 To LenB(bigU) - 1) ' 0 to 10 -1 CopyMemory ByVal VarPtr(ba(0)), bigU, LenB(bigU) End Sub ' ' end code While this is all straightforward with this set of UDTs with all declared numeric members, be careful as with variants, strings (particularly if any unicode) and arrays in UDTs internally, the data may not line up as simply as in this example. Your "GetUdtPointer" function is misnamed, it doesn't return a pointer. Also there isn't a "pointer to a specific Utdb" as the specific Utdb you're talking about doesn't exist until reconstructed, merely the relevant byte offset from the main udt's pointer as illustrated. Just as series of bytes any portion of which could be reconstrated to say a byte array or somthing else. If you explain the real objective for all this maybe there is a different sort of answer. Peter T |
Reply |
Thread Tools | Search this Thread |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Forum | |||
Compile error: User-defined type not defined | Excel Programming | |||
Help: Compile error: type mismatch: array or user defined type expected | Excel Programming | |||
Workspace faux user-defined type not defined | Excel Programming | |||
User-defined data type; Error: Only User-defined types... | Excel Programming | |||
User defined type problem | Excel Programming |