[updated topic] member function ptr

General FreeBASIC programming questions.
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

[updated topic] member function ptr

Post by dafhi »

goal: access different functions, based upon value given at constructor

(this isn't meant to compile .. showing my idea)

Code: Select all

type mytype extends object
  declare operator cast as string
  declare          constructor( as string )
  declare function aa as single
  declare function bb as single
  ' .. other functions
End Type

constructor mytype( _s as string )
  pf = @bb
  if _s = "" then pf = @aa
end constructor

function mytype.aa as single
  return -1
end function

function mytype.bb as single
  return 0
end function
Last edited by dafhi on Nov 28, 2019 11:23, edited 3 times in total.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: property ptr possible?

Post by D.J.Peters »

An property can't be a static class member ! (so far I know)

Joishy
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: [updated topic] member function ptr

Post by dodicat »

Hi dafhi.
They have to be static to get their address in memory.
There are horrible looking hacks, but too awful to remember.

Code: Select all

 type mytype extends object
  declare operator cast as string
  declare          constructor( as string )
  declare static function aa as single
  declare static function bb as single
  ' .. other functions
End Type

constructor mytype( _s as string )
var pf = @bb
  if _s = "" then pf = @aa
  print pf,pf()
end constructor

function mytype.aa as single
  return -1
end function

function mytype.bb as single
  return 0
end function
dim as mytype x="",y="Hello"
sleep


dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

lol. thanks dodicat

it's past my bedtime .. ill try it out tomorrow
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: [updated topic] member function ptr

Post by paul doe »

Is this what you meant?

Code: Select all

type _
  Foo _
  extends Object
  
  public:
    declare constructor()
    declare constructor( _
      byref as const string )
    declare virtual destructor()
    
    declare function _
      bar() as single
    
  private:
    declare static function _
      f1( _
        byval as Foo ptr ) _
      as single
    declare static function _
      f2( _
        byval as Foo ptr ) _
      as single
    
    as function( _
      byval as Foo ptr ) as single _
      _privateFunc
    
    as single _
      _baz => -4.0
end type

constructor _
  Foo()
  
  this.constructor( "" )
end constructor

constructor _
  Foo( _
    byref aString as const string )
  
  if( aString = "" ) then
    _privateFunc => @f1
  else
    _privateFunc => @f2
  end if
end constructor

destructor _
  Foo()
end destructor

function _
  Foo.bar() _
  as single
  
  return( _privateFunc( @this ) )
end function

function _
  Foo.f1( _
    byval aFoo as Foo ptr ) _
  as single
  
  return( aFoo->_baz * 2 )
end function

function _
  Foo.f2( _
    byval aFoo as Foo ptr ) _
  as single
  
  return( aFoo->_baz * 1.5 )
end function

/'
  Test code
'/
var _
  foo1 => Foo( "bar" ), _
  foo2 => Foo()

? foo1.bar()
? foo2.bar()

sleep()
Although what usefulness could this have is beyond me. Perhaps you can elaborate a little on what you want to achieve?
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: [updated topic] member function ptr

Post by fxm »

dodicat wrote:There are horrible looking hacks, but too awful to remember.
  • (a remind for you)
Hacking workaround

When a member procedure is declared "virtual", one can hack the address of its static version in the vtable of the object:

Code: Select all

type mytype extends object
  public:
    declare constructor(byref as string )
    declare virtual function aa() as single
    declare virtual function bb() as single
    declare function pf() as single
  private:
    dim _pf as function (Byref as mytype) as single
End Type

#define referVirtualFunction(virtualFunctionNb) Cptr(Any Ptr Ptr Ptr, @This)[0][virtualFunctionNb]

constructor mytype(byref _s as string )
  _pf = referVirtualFunction(1)
  if _s = "" then _pf = referVirtualFunction(0)
end constructor

function mytype.aa() as single
  print "mytype.aa()"
  return -1
end function

function mytype.bb() as single
  print "mytype.bb()"
  return 0
end function

function mytype.pf() as single
  return this._pf(this)
end function

dim mytype1 as mytype = mytype("")
print mytype1.pf()
print
dim mytype2 as mytype = mytype("x")
print mytype2.pf()

sleep
[edit]
Added macro to simplify the function referencing.
Last edited by fxm on Nov 29, 2019 8:35, edited 1 time in total.
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

paul doe

Code: Select all

dim as mytype a(2) = {"a", "b", "c"}

for x as integer = 0 to w-1
  var q = 0f
  for i as integer = 0 to ubound(a)
    q += a(i)
  Next
Next
fxm - that's insane in a good way
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: [updated topic] member function ptr

Post by paul doe »

@dafhi: ok, but that does not tell me anything about its use case...
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

user-defined wave function sequence

is that what you mean by use case? I'm using it for my palette gen
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: [updated topic] member function ptr

Post by paul doe »

dafhi wrote:additive waveforms. is that what you mean by use case?
Indeed. Yes, I can see its usefulness now (although a more 'common' approach would simply involve subclassing the appropriate classes from a base class). If efficiency is a concern, this approach might have some merit, unless you need to deal with identities, naturally.
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

it's about efficiency. per-pixel kind of thing :D
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: [updated topic] member function ptr

Post by paul doe »

If that's the case, wouldn't it be better to simply code it as a function and pass it the appropriate context? Why do you need a 'class' for that?
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

evolving my own style
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: [updated topic] member function ptr

Post by fxm »

fxm wrote: Hacking workaround

When a member procedure is declared "virtual", one can hack the address of its static version in the vtable of the object:

Code: Select all

type mytype extends object
  public:
    declare constructor(byref as string )
    declare virtual function aa() as single
    declare virtual function bb() as single
    declare function pf() as single
  private:
    dim _pf as function (Byref as mytype) as single
End Type

#define referVirtualFunction(virtualFunctionNb) Cptr(Any Ptr Ptr Ptr, @This)[0][virtualFunctionNb]

constructor mytype(byref _s as string )
  _pf = referVirtualFunction(1)
  if _s = "" then _pf = referVirtualFunction(0)
end constructor

function mytype.aa() as single
  print "mytype.aa()"
  return -1
end function

function mytype.bb() as single
  print "mytype.bb()"
  return 0
end function

function mytype.pf() as single
  return this._pf(this)
end function

dim mytype1 as mytype = mytype("")
print mytype1.pf()
print
dim mytype2 as mytype = mytype("x")
print mytype2.pf()

sleep
Variant using polymorphism by hacking the vptr of the object this time and no longer the vtable (with a child class for each member function to refer):

Code: Select all

type mytype extends object
    declare constructor()
    declare constructor(byref as string)
    declare virtual function xx() as single
End Type

constructor mytype()
end constructor

#define downCastObject(typename) Cptr(any ptr ptr, @this)[0] = Cptr(any ptr ptr, @typename())[0]

function mytype.xx() as single
    return -1/0
end function

type mytypeaa extends mytype  '' must contain only procedure members (no data member)
    declare virtual function xx() as single
end type 

function mytypeaa.xx() as single
  print "mytypeaa.xx()"
  return -1
end function

type mytypebb extends mytype  '' must contain only procedure members (no data member)
    declare virtual function xx() as single
end type 

function mytypebb.xx() as single
  print "mytypebb.xx()"
  return 0
end function

constructor mytype(byref _s as string)
    downCastObject(mytypebb)
    if _s = "" then downCastObject(mytypeaa)
end constructor

dim mytype1 as mytype = mytype("")
print mytype1.xx()
print
dim mytype2 as mytype = mytype("x")
print mytype2.xx()

sleep
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

Re: [updated topic] member function ptr

Post by dafhi »

[update 3] trying to do something like this

Code: Select all

' faster than int()   http://www.freebasic.net/forum/viewtopic.php?p=118633
#define flo(x)        (((x)*2.0-0.5)shr 1)
  
  
  type func_vars extends object
    decl constructor      ( sng = .5, sng = .5, sng = 0, sng = 1 )
    decl virtual function wave( sng ) sng
    decl sub              function_path( as string )
   protected:
    sng                   clip_hi
    sng                   clip_lo
    sng                   off_y
    sng                   amp
  End Type
  
  function func_vars.wave( i sng ) sng:  return -1/0
  End Function
  
  
  '' polymorphism emulation (?)  courtesy of fxm
  type func_sw extends func_vars
    decl virtual function wave( sng ) sng
  End Type
 
  function func_sw.wave( i sng ) sng
    
    '' sawtooth:  [range -.5 to .5]
    i = (i - flo(i) - .5) * amp + off_y

    return i + _
      ( i - clip_hi ) * ( i > clip_hi ) + _
      ( i - clip_lo ) * ( i < clip_lo )
  End function
  
  
  type func_tr extends func_vars
    decl virtual function wave( sng ) sng
  End Type
  
  function func_tr.wave( i sng ) sng
    
    '' triangle:  [range -.25 to .25]
    i = ( abs(i - flo(i) - .5) - .25 ) * amp + off_y  '' modified Stonemonkey formula

    return i + _
      ( i - clip_hi ) * ( i > clip_hi ) + _
      ( i - clip_lo ) * ( i < clip_lo )
  End function
  
  
  '' back to regularly scheduled programming
  constructor func_vars( hi sng, lo sng, off sng, _amp sng )', wave_name as string )
    clip_hi = hi
    clip_lo = lo
    off_y = off
    amp = _amp
  End constructor
  
  sub func_vars.function_path( wave_name as string )
    #define polymorph_hack(fname) _
      Cptr(any ptr ptr, @this)[0] = Cptr(any ptr ptr, @fname())[0]
    select case lcase( left(wave_name,3) )
    case "saw"
      polymorph_hack(func_sw)
    case else
      polymorph_hack(func_tr)
    End Select
  End Sub
old functions which fxm (on next page) identified as problematic

Code: Select all

  constructor func_vars( lo sng, hi sng, off sng, amp sng, wave_name as string )
    values lo,hi,off,amp, tr
    if lcase( left(wave_name,3) ) <> "tri" then values lo,hi,off,amp*2, sw
  End constructor
  
  sub func_vars.values( lo sng, hi sng, off sng, amp sng, pf as function ( sng ) sng )
    this = type(lo,hi,off,amp)
    wave = @pf
  End Sub
thanks paul doe & fxm. i did see 'This' as a parameter. Hopefully there's a way around that
Last edited by dafhi on Dec 02, 2019 7:20, edited 2 times in total.
Post Reply