Objects & Static Event Handlers: How To Access Non-Static Members?

General FreeBASIC programming questions.
Munair
Posts: 374
Joined: Oct 19, 2017 15:00
Location: 't Zand, NL
Contact:

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby Munair » Nov 20, 2017 18:04

fxm wrote:Yes, but any access to data field of myW cannot work (and even that may crash) by principle:

Yes, wrong segment. Is there a work-around for this? In a similar thread from 2010 I saw two macros, but I really cannot make heads or tales of them as they also seem to include external code:

Code: Select all

#macro eventsub (subname, funcname, params)
   sub subname.funcname##Static cdecl (params)
    (*(cptr(subname ptr, sbgui.getId(sbgui.getWindow(eventPtr))))).funcname (eventPtr)
   end sub
   sub subname.funcname (params)
#endmacro

#macro eventfunction (subname, funcname, params)
   function subname.funcname##Static cdecl (params) as uinteger
      return (*(cptr(subname ptr, sbgui.getId(sbgui.getWindow(eventPtr))))).funcname (eventPtr)
   end function
   function subname.funcname (params) as uinteger
#endmacro

/'
example
'/
Sbgui.getId(sbgui.getWindow(eventPtr)) 'holds the address to the UDT instance. eventPtr the parameter sent to the function from "outside".

sbgui.setId (window, cptr(uinteger ptr, @this))

sbgui.subscribeEvent (window, "Sized", cptr(uinteger ptr, cptr(uinteger ptr, procptr(merchantWindowUDT.sizedEventStatic))))
/'
fxm
Posts: 7492
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby fxm » Nov 20, 2017 18:48

A workaround for example (static function without parameter and instance pointer passed through a static member variable):

Code: Select all

' window object
type fxW extends object
   title as string
end type

' menu object
type fxM extends object
   clickevent as sub
end type

' custom window
type myW extends fxW
   myM as fxM
   declare static sub clickhandler()
   static me as myW Ptr
   declare sub ButtonClick()
   declare constructor()
   declare destructor()
   I as integer = 123
end type
dim myW.me as myW Ptr

constructor myW
 print __function__
   title = "Window 1"
   myM.clickevent = @clickhandler
   me = @This
end constructor

destructor myW
print "done"
sleep 500
end destructor

sub myW.ButtonClick()
     print __function__
end sub

static sub myW.clickhandler()
   print __function__
   me->ButtonClick()
   print me->I
end sub

dim as MyW win
print win.title
win.myM.clickevent()
sleep

Code: Select all

MYW.constructor
Window 1
MYW.CLICKHANDLER
MYW.BUTTONCLICK
 123
Munair
Posts: 374
Joined: Oct 19, 2017 15:00
Location: 't Zand, NL
Contact:

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby Munair » Nov 20, 2017 19:14

@fxm I already tried a static pointer. While your example works, I still get undefined reference error with the static pointer:

Code: Select all

fbc -w all "test-menu.bas"
test-menu.o: In function `TFMAIN::TFMAIN()':
test-menu.c:(.text+0x24f5): undefined reference to `TFMAIN::ME$'
test-menu.o: In function `TFMAIN::SUBMENUITEM1_CLICKHANDLER_()':
test-menu.c:(.text+0x2816): undefined reference to `TFMAIN::ME$'
test-menu.o: In function `TFMAIN::SUBMENUITEM2_CLICKHANDLER_()':
test-menu.c:(.text+0x282c): undefined reference to `TFMAIN::ME$'
test-menu.o: In function `TFMAIN::SUBMENUITEM3_CLICKHANDLER_()':
test-menu.c:(.text+0x2842): undefined reference to `TFMAIN::ME$'
test-menu.o: In function `TFMAIN::SUBMENUITEM4_CLICKHANDLER_()':
test-menu.c:(.text+0x2858): undefined reference to `TFMAIN::ME$'
I will go over your code to see if there is any notable difference.
fxm
Posts: 7492
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby fxm » Nov 20, 2017 19:22

The line 21 ('dim myW.me as myW Ptr') is mandatory for defining a static member data.
('static me as myW Ptr' is only the declaration)
Munair
Posts: 374
Joined: Oct 19, 2017 15:00
Location: 't Zand, NL
Contact:

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby Munair » Nov 20, 2017 19:29

fxm wrote:The line 21 ('dim myW.me as myW Ptr') is mandatory for defining a static member data.
('static me as myW Ptr' is only the declaration)

LOL I overlooked that sneaky line glued to the Type. Thanks
Munair
Posts: 374
Joined: Oct 19, 2017 15:00
Location: 't Zand, NL
Contact:

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby Munair » Nov 20, 2017 20:07

Screenshot of successfully compiled code: viewtopic.php?f=8&p=239735#p239735
dodicat
Posts: 4495
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby dodicat » Nov 21, 2017 1:20

Sorry about the null pointer.
Maybe a temporary udt would simplify things.
Seems safe enough now.

Code: Select all

 ' window object
type fxW extends object
   title as string
end type

' menu object
type fxM extends object
   clickevent as sub
end type

' custom window
type myW extends fxW
   myM as fxM
   declare static sub clickhandler()
   declare sub ButtonClick()
   declare constructor()
   declare destructor()
end type

constructor myW
 print __function__
   title = "Window 1"
   myM.clickevent = cast(sub,@clickhandler)
end constructor

destructor myW
print "done"
sleep 500
end destructor

sub myW.ButtonClick()
     print __function__
end sub

 sub myW.clickhandler()
    print __function__
    type<MyW>.buttonclick()
end sub

dim as MyW win
print win.title
win.myM.clickevent()

sleep

 

Although you have it running with the static field element OK
Munair
Posts: 374
Joined: Oct 19, 2017 15:00
Location: 't Zand, NL
Contact:

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby Munair » Nov 21, 2017 9:26

@dodicat. It's a no-go. Changes made in the ButtonClick handler are not preserved:

Code: Select all

 ' window object
type fxW extends object
   title as string
end type

' menu object
type fxM extends object
   clickevent as sub
end type

' custom window
type myW extends fxW
   myM as fxM
   declare static sub clickhandler()
   declare sub ButtonClick()
   declare constructor()
   declare destructor()
end type

constructor myW
 print __function__
   title = "Window 1"
   myM.clickevent = cast(sub,@clickhandler)
end constructor

destructor myW
print "done"
sleep 500
end destructor

sub myW.ButtonClick()
     print __function__
     title = "wrong"
     print title
end sub

 sub myW.clickhandler()
    print __function__
    type<MyW>.buttonclick()
end sub

dim as MyW win
print win.title
win.myM.clickevent()
print win.title
sleep
end
fxm
Posts: 7492
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: Objects & Static Event Handlers: How To Access Non-Static Members?

Postby fxm » Nov 21, 2017 9:43

Obviously!

dodicat wrote:Sorry about the null pointer.
The pointer value was not null but anything, since it was extracted from the stack (due to 'sub myW.clickhandler(as myW ptr)') but not put in the stack (due to 'win.myM.clickevent()')

Remark:
1) We can always call a non virtual member procedure (even a static member procedure) on an irrelevant pointer value (including the null value):
- Because this pointer value is only passed as a under the hood parameter to the non-static member procedure to initialize its hidden reference "This".
- The program only crashes if it attempts to access a non static member data because none constructed object corresponds to the pointer value.
2) If we call a virtual member procedure on an irrelevant pointer value (including the null value), the crash is immediate because the vptr value (to access the vtable) is inconsistent.

Example:

Code: Select all

Type UDT
  Dim As Integer I
  Declare Sub test ()
End Type

Sub UDT.test ()
  Print "@This=" & @This
End Sub

Dim As UDT PTR pUDT = Cptr(Any Ptr, 123456789)
Print "pUDT=" & pUDT
pUDT->test()
Sleep
program wrote:pUDT=123456789
@This=123456789

Return to “General”

Who is online

Users browsing this forum: No registered users and 3 guests