May 01, 2024, 06:25:57 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


using 'as ANYTYPE'

Started by LarryMc, January 05, 2009, 07:44:44 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

In a subroutine I want to pass a parameter (dat)that will either be a pointer to a function (&myfunction) or
it can be an array of udt's

In determining what type is passed are these the right 'typeofs' to test for:

select typeof (dat)
   case @TYPEUINT
     '&myfunction was passed
   case @TYPEUSER
     ' an array of udts was passed
endselect

If not then what are the correct cases to use?

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Appears the above is the correct.

both appear to pass an 8 byte (UINT)

if the array unit that is passed is assigned to a udt element ( p.datsrc ) then
how do I retrieve the array data?

double z[20]
for x=0 to 19
  z[x] = x+0.0
next x

I passed in z
In the sub I assigned the value:
   p.datsrc = ##<UINT>z

later I want to read and print the data

for x=0 to 19
   print p.datsrc[x]     <---- I tried everything I could think of here and I can't get it to print  >:(
next x


Need some help please

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

the ANYTYPE can be represented as a structure:
TYPE ANYTYPE_T
union
int lValue
pointer pValue
float fValue /* and so on */
endunion
int nType
ENDTPE

And this is what I have used in TrialwareDialog example:
sub SetProperty(LPWSTR property, anytype value)
pointer p = &value

select typeof(value)
case @TYPEWSTRING
local_wide_string = *<wstring>p


Using the ANYTYPE_T structure it would be
local_wide_string = *<ANYTYPE_T>p.*<wstring>pValue

If speaking about doubles, the ANYTYPE cannot store a double because double requires 8 bytes, so the pValue holds a pointer to double, TYPEOF() returns @TYPEDOUBLE, and probably ISREF() will return TRUE.

fasecero

January 05, 2009, 10:22:05 AM #3 Last Edit: January 05, 2009, 10:28:08 AM by fasecero
This small example shows that the function is not recognized, the array's of udt's return  @TYPEUSER 


'console window example
'Compile for a CONSOLE target

TYPE SOMEUDT
INT something
ENDTYPE

OPENCONSOLE
' THE POINTER
DEF p AS pointer

' PASSING A POINTER TO A FUNCTION TO PointerGetType
' LET'S SEE WHAT RETURN
p=&myfunction
PRINT "pointing to a function return ?: "+str$(PointerGetType(#p)) 'nop!

' NOW WILL POINT TO AN ARRAY OF OF UDT'S
SOMEUDT udt[10]
p=udt
PRINT "pointing to an udt array ?: "+str$(PointerGetType(#p)) 'nop!

PRINT "Press any key to close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE

END

' FUNCTION TO GET THE POINTER TYPE
SUB PointerGetType(ANYTYPE dat), INT
INT answer
SELECT TYPEOF (dat)
CASE @TYPECHAR : answer = 1
CASE @TYPEINT : answer = 2
CASE @TYPEFLOAT : answer = 3
CASE @TYPEMEMORY : answer = 4
CASE @TYPEFILE : answer = 5
CASE @TYPEBFILE : answer = 6
CASE @TYPEWORD : answer = 7
CASE @TYPEDOUBLE : answer = 8
CASE @TYPEUSER : answer = 9
CASE @TYPEPOINTER : answer = 10
CASE @TYPEINT64 : answer = 11
CASE @TYPEUINT64 : answer = 12
CASE @TYPEUINT : answer = 13
DEFAULT : answer = 1000
ENDSELECT
RETURN answer
ENDSUB

SUB myfunction(),STRING
RETURN "hello"
ENDSUB

Ionic Wind Support Team

TYPE_USER is the correct answer.  Arrays are passed by reference so there is no way for the compiler to tell whether or not its a single element or an array, but that doesn't matter in this case as UDT (TYPE_USER) are passed by reference as well. 

The ANYTYPE parameter is an internal type used by a few built in commands, it was never meant for general use, but Sapero has gleaned most of the functionality from it.  ISREF tells you whether or not the parameter is a reference or value.  TYPEOF returns the internal ebasic type identifier.

You can send an array of UDT's like so:


type testtype
float f
int i
endtype

testtype t[5]
for x=0 to 4
t[x].f = x * 1.0f
t[x].i = x
next x
printit(t,5)
printit("Done",0)
do:until inkey$<>""

sub printit(value as anytype,count as int)
select typeof(value)
case @TYPEUSER
pointer p = ##<testtype>value
for x=0 to count-1
print #<testtype>p[x].f
print #<testtype>p[x].i
next x
case @TYPESTRING
print ##<string>value
endselect
endsub


Obviously the sender and the sendee need to agree on what the contents of the UDT are, as there is no way to glean the typename used when defining the UDT, since none of that is part of the machine code generated.

Microsoft uses there own paradigm when designing a function that can take multiple UDT (structure) definitions.  Which is to always have a dwSize member of the UDT, so the function can compare the size of the sent UDT to what it expects.

Paul.
Ionic Wind Support Team

LarryMc

Thanks for the responses

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

fasecero

I have been played with this today, it can be useful to me :). This code returns a pointer to a function like @TYPEUINT and udt's like @TYPEUSER


'console window example
'Compile for a CONSOLE target

TYPE SOMEUDT
INT something
ENDTYPE

OPENCONSOLE
' PASSING A POINTER TO A FUNCTION TO PointerGetType
' LET'S SEE WHAT RETURN
PRINT "pointing to a function return ?: "+str$(PointerGetType(&myfunction))

' NOW WILL POINT TO AN ARRAY OF UDT'S
SOMEUDT udt[10]
PRINT "pointing to an udt array ?: "+str$(PointerGetType(udt))

PRINT "Press any key to close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE

END

' FUNCTION TO GET THE POINTER TYPE
SUB PointerGetType(ANYTYPE dat), INT
DEF p AS pointer
p=&dat
INT answer
SELECT TYPEOF (dat)
CASE @TYPECHAR : answer = 1
CASE @TYPEINT : answer = 2
CASE @TYPEFLOAT : answer = 3
CASE @TYPEMEMORY : answer = 4
CASE @TYPEFILE : answer = 5
CASE @TYPEBFILE : answer = 6
CASE @TYPEWORD : answer = 7
CASE @TYPEDOUBLE : answer = 8
CASE @TYPEUSER : answer = 9
CASE @TYPEPOINTER : answer = 10
CASE @TYPEINT64 : answer = 11
CASE @TYPEUINT64 : answer = 12
CASE @TYPEUINT : answer = 13
DEFAULT : answer = 1000
ENDSELECT
RETURN answer
ENDSUB

SUB myfunction(),STRING
RETURN "hello"
ENDSUB


LarryMc

I can't get this to print the array correctly.  The array elements are garbage.
I always seem to have problems of some sort when I use pointers.

Any help would be appreciated.

type testtype
float f
int i
endtype

type mytype
int g
testtype u
endtype

pointer mylist
mylist = ListCreate()

testtype z[10]
int c
for c=0 to 9
z[c].f = c * 1.0f
z[c].i = c
next c

pointer temp = ListAdd(mylist,NEW(mytype,1))
#<mytype>temp.g = 43
#<mytype>temp.u = z

FOR element = EACH myList AS myType
   PRINT #element.g
printit(#element.u)
NEXT


printit("Done")
ListRemoveAll(myList, TRUE)
do:until inkey$<>""

sub printit(value as anytype)
select typeof(value)
case @TYPEUSER
pointer p = ##<testtype>value
for x=0 to 9
print #<testtype>p[x].f
print #<testtype>p[x].i
next x
case @TYPESTRING
print ##<string>value
endselect
endsub


Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Actually it is doing exactly what you are telling it.

pointer temp = ListAdd(mylist,NEW(mytype,1))
#<mytype>temp.g = 43
#<mytype>temp.u = z   

You only have 1 testtype UDT being assigned.  And in the sub you are trying to access 10 of them.  Since #<mytype>temp.u is not an array and that is what you are passing here:

printit(#element.u)

#element.u is just a single UDT, not an array of them, you defined it as such in your added UDT:

type mytype
   int g
   testtype u:'<-----ONE udt
endtype

Now if you wanted to have an array of 10 of them it would be:

type mytype
   int g
   testtype u[10]
endtype

But you couldn't just copy them from z to u with an assignment statement, you would need to loop.  Then again you wouldn't need z at all, unless you just happen to need it somewhere else. In anyevent by eliminating z, and moving the initial loop you can achieve what you want.


type testtype
float f
int i
endtype

type mytype
int g
testtype u[10]
endtype

pointer mylist
mylist = ListCreate()

int c

pointer temp = ListAdd(mylist,NEW(mytype,1))
#<mytype>temp.g = 43
for c=0 to 9
#<mytype>temp.u[c].f = c * 1.0f
#<mytype>temp.u[c].i = c
next c

FOR element = EACH myList AS myType
   PRINT #element.g
printit(#element.u)
NEXT


printit("Done")
ListRemoveAll(myList, TRUE)
do:until inkey$<>""

sub printit(value as anytype)
select typeof(value)
case @TYPEUSER
pointer p = ##<testtype>value
for x=0 to 9
print #<testtype>p[x].f
print #<testtype>p[x].i
next x
case @TYPESTRING
print ##<string>value
endselect
endsub


Paul.
Ionic Wind Support Team

LarryMc

Paul,I understand what you are telling me.
It is easy for me to see it now.
What you proposed works but it doesn't do what I want it to do.

What you proposed  (with my type declaration ) is have a predefined size(10) for the udt array.
I can't have it that way.
The 1st thing I have to do is change my type code from
type mytype
int g
testtype u[10]
endtype
to
type mytype
int g
pointer k   'or possibly a uint that is a pointer; got to play with it to see
endtype

so that g contains the # of elements in the array and k is used to find the address of the array

I'll see if I can figure out the code from there; if not you know I'll holler again.

Thanks for taking the time to explain it in detail for me.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

This is structured the way I need it to work but it doesn't work and I don't know what to do to fix it.
type testtype
float f
int i
endtype

type mytype
int g
pointer u
endtype

pointer mylist
mylist = ListCreate()

testtype z[10]
int c
for c=0 to 9
z[c].f = c * 1.0f
z[c].i = c
next c

pointer temp = ListAdd(mylist,NEW(mytype,1))
#<mytype>temp.g = 10
#<mytype>temp.u = &z

FOR element = EACH myList AS myType
printit2(#element.u,#element.g)
NEXT

print "Done"
ListRemoveAll(myList, TRUE)
do:until inkey$<>""

sub printit2(value :pointer,cnt:int)
int x
print "cnt ",cnt
for x=0 to cnt-1
print #<testtype>value.f[x]
print #<testtype>value.i[x]
next x
return
endsub


Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

January 08, 2009, 12:51:33 PM #11 Last Edit: January 08, 2009, 12:57:01 PM by Paul Turley
      print #<testtype>value.f[ x ]
      print #<testtype>value.i[ x ]

should be:

      print #<testtype>value[ x ].f
      print #<testtype>value[ x ].i

Ionic Wind Support Team

LarryMc

January 08, 2009, 12:55:42 PM #12 Last Edit: January 08, 2009, 01:00:50 PM by Larry McCaughn
I don't know what the little black squares are?

Larry

EDIT:  I see what you intended the index "x" and the brackets are in the wrong place.
I moved it after the "value"
i.e it now looks likeprint #<testtype>value[  x  ].f

I FIGURED IT OUT WHILE YOU WERE TYPING,

THANKS

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

lol.  Look again.  [ x ] without the spaces causes the forum to print a block
Ionic Wind Support Team