Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 28
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 7
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 28
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 7
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 28
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 162
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 28
Default 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   Report Post  
Posted to microsoft.public.excel.programming
external usenet poster
 
Posts: 162
Default 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
Search this Thread:

Advanced Search
Display Modes

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Compile error: User-defined type not defined Ayo Excel Programming 3 April 23rd 09 07:42 PM
Help: Compile error: type mismatch: array or user defined type expected lvcha.gouqizi Excel Programming 1 October 31st 05 08:20 PM
Workspace faux user-defined type not defined Chris S[_2_] Excel Programming 3 November 11th 04 05:51 PM
User-defined data type; Error: Only User-defined types... tiger_PRM Excel Programming 1 July 18th 04 03:32 PM
User defined type problem R Avery Excel Programming 1 May 26th 04 02:41 PM


All times are GMT +1. The time now is 01:29 PM.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2004-2024 ExcelBanter.
The comments are property of their posters.
 

About Us

"It's about Microsoft Excel"