Allow to change a structure of a pointer

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
infratec
Always Here
Always Here
Posts: 7591
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Allow to change a structure of a pointer

Post by infratec »

Hi,

it would be nice if something like this is possible:

Code: Select all

If Type = 1
  *ptr.Type1Str = *Buffer
else
  *ptr.Type2Str = *Buffer
endif
Bernd
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: Allow to change a structure of a pointer

Post by ts-soft »

This is possible :wink:

//edit
not to create a structure at runtime, but to use different structures
Last edited by ts-soft on Fri Jan 20, 2012 5:32 pm, edited 1 time in total.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Allow to change a structure of a pointer

Post by Fred »

Well, if you can change the structure at runtime, how will you access the fields if the structure have different fiels ? It needs to known at compile time, as PB isn't an interpreted language.
User avatar
STARGÅTE
Addict
Addict
Posts: 2227
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Allow to change a structure of a pointer

Post by STARGÅTE »

use structure union:

Code: Select all

Structure BothTypes
	StructureUnion
		Type1.Type1Str
		Type2.Type2Str
	EndStructureUnion
EndStructure

*ptr.BothTypes = *Buffer
If Type = 1
  *ptr\Type1\...
Else
  *ptr\Type2\...
EndIf 
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
infratec
Always Here
Always Here
Posts: 7591
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Allow to change a structure of a pointer

Post by infratec »

@Stargate

That's clear, but not what I need.
In your case I have to use the whole time a different name to access the structure. :cry:

At the moment I solve it this way:

Code: Select all

If ChannelRecordSize = 100
  ReadChannel.Prototype_ReadChannel = @ReadChannel100()
ElseIf ChannelRecordSize = 476
  ReadChannel.Prototype_ReadChannel = @ReadChannel476()
EndIf
Than I can call the 'same' procedure: ReadChannel(*Buffer + Ptr) for the rest of the program :wink:

But I need 2 procedures which are completely identical up to the structure which I use for the pointer:

Code: Select all

Procedure ReadChannel100(*Channel.Channel100Str)

Code: Select all

Procedure ReadChannel476(*Channel.Channel476Str)
Bernd
User avatar
helpy
Enthusiast
Enthusiast
Posts: 552
Joined: Sat Jun 28, 2003 12:01 am

Re: Allow to change a structure of a pointer

Post by helpy »

Hi,

I do not see any way to do this in PureBasic, if both structures are completely different.

If both structures are extended from a base structure and the procedure only uses the base elements, you could do the following:

Code: Select all

Structure ChannelBase
	; base elements
EndStructure

Structure Channel100Str Extends ChannelBase
	; 100Str specific elements
EndStructure

Structure Channel476Str Extends ChannelBase
	; 476Str specific elements
EndStructure

Procedure ReadChannel( *Channel.ChannelBase )
	; ....
EndProcedure

; ....

ReadChannel( *ptr100Str )

; ....

ReadChannel( *ptr476Str )

; ....

After all there maybe is a way ... hmmm ....
You could create a standardized structure and COPY all elements from the original structure to the standardized one, which is handled by the Procedure ReadChannel(*Channel.ChannelStandardized).

cu,
guido
Windows 10 / Windows 7
PB Last Final / Last Beta Testing
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Allow to change a structure of a pointer

Post by breeze4me »

I think anonymous structure union will be more useful.

Something like this.

Code: Select all

Structure BothTypes
  StructureUnion
    AnonymousStructure Type1Str
    AnonymousStructure Type2Str
  EndStructureUnion
EndStructure

*ptr.BothTypes = *Buffer
or

Code: Select all

Structure BothTypes
  StructureUnion
    AnonymousStructure   ;Type1Str
      ......
    EndAnonymousStructure
    AnonymousStructure   ;Type2Str
      ......
    EndAnonymousStructure
  EndStructureUnion
EndStructure
Edit:
Never mind.
This way has a problem.
Last edited by breeze4me on Sat Jan 21, 2012 4:58 pm, edited 2 times in total.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Allow to change a structure of a pointer

Post by Trond »

infratec wrote:But I need 2 procedures which are completely identical up to the structure which I use for the pointer:

Code: Select all

Procedure ReadChannel100(*Channel.Channel100Str)

Code: Select all

Procedure ReadChannel476(*Channel.Channel476Str)
Bernd
If what you say is true (the procedures are actually, truly, identical) then, by definition, one structure must be a subset of the other, else field lookup wouldn't work. In this case, just pass in the address of the variable + the offset in the structure where the subset starts, and it will work regardless of declared structure.

It would help if you showed us the structures.

If you want runtime duck typing then make your structure contain a single map and shove all your members in there.
infratec
Always Here
Always Here
Posts: 7591
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Allow to change a structure of a pointer

Post by infratec »

Hi Trond,

Here is what you want:

Code: Select all

Structure Channel100Str
  Name.s{32}
  Dummy0.a[12]
  Transponder.a
  Dummy1.a[15]
  ServiceID.u
EndStructure

Structure Channel476Str
  Name.s{32}
  Dummy0.a[12]
  Transponder.a
  Dummy1.a[391]
  ServiceID.u
EndStructure

Prototype Prototype_ReadChannel(*Channel)
Global ReadChannel.Prototype_ReadChannel

Procedure ReadChannel100(*Channel.Channel100Str)
  Channel$ = *Channel\Name + #LF$
  Channel$ + Str(*Channel\Transponder) + #LF$
  Channel$ + Str(*Channel\ServiceID)
  AddGadgetItem(0, -1, Channel$)
EndProcedure


Procedure ReadChannel476(*Channel.Channel476Str)
  Channel$ = *Channel\Name + #LF$
  Channel$ + Str(*Channel\Transponder) + #LF$
  Channel$ + Str(*Channel\ServiceID)
  AddGadgetItem(0, -1, Channel$)
EndProcedure
Depending on the 'version' of the file which I process, I use one or the other:

Code: Select all

:
:
:
If ChannelRecordSize = 100
  ReadChannel.Prototype_ReadChannel = @ReadChannel100()
ElseIf ChannelRecordSize = 476
  ReadChannel.Prototype_ReadChannel = @ReadChannel476()
EndIf

ClearGadgetItems(0)
For i = 1 To Channels
  ReadChannel(*Buffer + Ptr)
  Ptr + ChannelRecordSize
Next i
:
:
:
My solution works, but it's 'ugly'.

Bernd
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: Allow to change a structure of a pointer

Post by Trond »

If it's coming from somewhere, the format is fixed and you can't do much about it. :(

But If you can swap the two last fields in both structures, or make both structures extend from one, with the field Dummy1 as the only field in each used structure, this can be solved elegantly:

Code: Select all

Structure ChannelStr
  Name.s{32}
  Dummy0.a[12]
  Transponder.a
  ServiceID.u
  Dummy1_.a[0]
EndStructure

Structure Channel100Str Extends ChannelStr
  Dummy1.a[15]
EndStructure

Structure Channel476Str Extends ChannelStr
  Dummy1.a[391]
EndStructure

Procedure ReadChannel(*Channel.ChannelStr)
  Channel$ = *Channel\Name + #LF$
  Channel$ + Str(*Channel\Transponder) + #LF$
  Channel$ + Str(*Channel\ServiceID)
  AddGadgetItem(0, -1, Channel$)
EndProcedure

ClearGadgetItems(0)
For i = 1 To Channels
  ReadChannel(*Buffer + Ptr)
  Ptr + ChannelRecordSize
Next i
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Allow to change a structure of a pointer

Post by skywalk »

Trond wrote:

Code: Select all

Structure ChannelStr
  Name.s{32}
  Dummy0.a[12]
  Transponder.a
  ServiceID.u
  ;
  Dummy1_.a[0]    ;<-- If you omit this, I assume the code will fail?
  ;
EndStructure

Structure Channel100Str Extends ChannelStr
  Dummy1.a[15]
EndStructure

Structure Channel476Str Extends ChannelStr
  Dummy1.a[391]
EndStructure
Nice. 8) I noticed this behavior a while back and thought it was a mistake.
Even though you don't reference the extended structure, the fields are there for the taking.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply