It is currently Sun Oct 25, 2020 6:21 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 12:57 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
mk-soft wrote:
P.S.
The call you wish for would have to be implemented by compiler.
Quote:
r1 = {IsObject *VT-stack1 = }\getA\{IsObject *VT-stack2 = }\getB\{IsObject *VT-stack3 = }\getC() {*VT-stack3\Release()} {*VT-stack2\Release()} {*VT-stack1\Release()}


Its not a wish what i showed works.
Unless this is not aimed at me but the original request.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 12:58 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2683
Location: Germany
You can provide functions in a structure. However, this has nothing to do with interfaces.
For this you have to define the function with ProtoType.
However, it is a problem to pass the pointer to your own data.
But there's one trick I've got to figure out...

Link: https://www.purebasic.fr/german/viewtop ... =8&t=30347

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Last edited by mk-soft on Sun Jul 15, 2018 1:06 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 1:01 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
mk-soft wrote:
You can provide functions in a structure. However, this has nothing to do with interfaces.
For this you have to define the function with ProtoType.
However, it is a problem to pass the pointer to your own data.
But there's one trick I've got to figure out...


Well this works just fine for me...
Code:
Structure PUBLIC_VTABLE_STRUCT
;...
  *Object.iObject;<- Interface !!!
EndStructure

And you always get the pointer to it, access it and or call any function...
Code:
Procedure.i Something(*VT.PUBLIC_VTABLE_STRUCT);<- function of the public interface
;...
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 5:05 pm 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
I looked at the suggestions provided by both mk-soft and Mijikai. The problem still comes down to functions being unable to return anything other than primitives.

Consider how I want to chain methods:

Code:
obj\getBox()\getWidth()


The problem lies squarely with the return value for getBox(). Because its return value cannot be defined as an interface or as a pointer to a specific structure, then the compiler cannot complete the chain.

Can't do any of these:

Code:
Declare.SomeStruct getBox()
Declare.SomeStruct* getBox()
Declare.SomeInterface getBox()


Only this for pointer results:

Code:
Declare.i getBox()


Therefore the chain cannot be completed:

Code:
getBox()\getWidth() <- how can it call getWidth()?


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 6:16 pm 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 1264
Location: right here
I guess return values are simply not lvalues
Code:
Procedure.s f(s.s)
  ProcedureReturn s
EndProcedure

Debug PeekS(@f("abc")) ; doesn't peek into a string temporary because it's just the same
Debug PeekS(@f())      ; as the function pointer

; output:
;   ㅈ僀䡐䠨襈⑄䠨䒋䀤襈뀅☒䠀璋⠤赈⑼䠨뇕荈Ⴤ襈䣦쟇
;   ㅈ僀䡐䠨襈⑄䠨䒋䀤襈뀅☒䠀璋⠤赈⑼䠨뇕荈Ⴤ襈䣦쟇


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sun Jul 15, 2018 6:23 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
Mistrel wrote:
I looked at the suggestions provided by both mk-soft and Mijikai. The problem still comes down to functions being unable to return anything other than primitives.

Consider how I want to chain methods:

Code:
obj\getBox()\getWidth()


The problem lies squarely with the return value for getBox(). Because its return value cannot be defined as an interface or as a pointer to a specific structure, then the compiler cannot complete the chain.

Can't do any of these:

Code:
Declare.SomeStruct getBox()
Declare.SomeStruct* getBox()
Declare.SomeInterface getBox()


Only this for pointer results:

Code:
Declare.i getBox()


Therefore the chain cannot be completed:

Code:
getBox()\getWidth() <- how can it call getWidth()?



You can assign any return value to the vtable - structure and use it directly or
through any of the interface functions.

Code:
Interface box
  GetWidth.i()
EndInterface

Interface obj
  GetBox.i()
  GetBoxWidth.i()
EndInterface

Structure OBJ_VTABLE
  ;...
  *Box.box;< - interface!!!
EndStructure

Structure OBJ_STRUCT
  StructureUnion
    *Interface.obj
    *VT.OBJ_VTABLE
  EndStructure
EndStructure

Global Object.OBJ_STRUCT

Procedure.i CreateObject()
  ;will create and return the object interface (with custom vtable)
EndProcedure

Procedure.i GetBoxInterface()
  ;will create/get a box interface!
EndProcedure

Procedure.i GetBox(*VT.OBJ_VTABLE);function of the object interface
  *VT\Box = GetBoxInterface();<- get the box interface and assign it to the vtable
EndProcedure

Procedure.i GetBoxWidth(*VT.OBJ_VTABLE);function of the obj interface
  ProcedureReturn *VT\Box\GetWidth()
EndProcedure

Object\Interface = CreateObject();<- create the object interface
Object\Interface\GetBox();<- get the box interface
Object\VT\Box\GetWidth();<- call GetWidth() directly through the vtable
Object\Interface\GetBoxWidth();<- call GetWidth() through a object interface function


I mean you could even just do this:

Code:
;...
Private *Box.box
*Box = Object\Interface\GetBox():*Box\GetWidth()
;...


If no access through the obj interface is required.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Mon Jul 16, 2018 2:54 am 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
Mijikai, I think you misunderstand. SomeObject is returning a BoxObject which has its own interface. In this example it only has one box. What if it's a collection of boxes?

Here is a more complete example if the current limitations and where the call chain gets stuck:

Code:
;/ -- [[ BoxObject ]]- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

DeclareModule BoxObject
  Interface Public
    getWidth()
    getHeight()
  EndInterface
 
  Structure VTable
    *getWidth
    *getHeight
  EndStructure
 
  Structure Class
    *vTable
    width.i
    height.i
  EndStructure
 
  ;/ Static
  Declare setVTable(*vTable.Class)
  Declare new()
EndDeclareModule

Module BoxObject
  ;/ Static
  Global vTable.VTable
  setVTable(@vTable)
 
  Procedure new()
    Protected *instance.Class
   
    *instance=AllocateStructure(Class)
    *instance\vTable=@vTable
   
    *instance\width=123
    *instance\height=456
   
    ProcedureReturn *instance
  EndProcedure
 
  Procedure getWidth(*this.Class)
    ProcedureReturn *this\width
  EndProcedure
 
  Procedure getHeight(*this.Class)
    ProcedureReturn *this\height
  EndProcedure
 
  Procedure setVTable(*vTable.VTable)
    *vTable\getWidth=@getWidth()
    *vTable\getHeight=@getHeight()
  EndProcedure
EndModule

Interface BoxObject Extends BoxObject::Public
EndInterface

;/ -- [[ SomeObject ]] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

DeclareModule SomeObject
  Interface Public
    getBox()
  EndInterface
 
  Structure VTable
    *getBox.getBox
  EndStructure
 
  Structure Class
    *vTable
    *box.BoxObject
  EndStructure
 
  ;/ Static
  Declare setVTable(*vTable.Class)
  Declare new()
EndDeclareModule

Module SomeObject
  ;/ Static
  Global vTable.VTable
  setVTable(@vTable)
 
  Procedure new()
    Protected *instance.Class
   
    *instance=AllocateStructure(Class)
    *instance\vTable=@vTable
   
    ;/ SomeObject has a BoxObject
    *instance\box=BoxObject::new()
   
    ProcedureReturn *instance
  EndProcedure
 
  Procedure getBox(*this.Class)
    ProcedureReturn *this\box
  EndProcedure
 
  Procedure setVTable(*vTable.VTable)
    *vTable\getBox=@getBox()
  EndProcedure
EndModule

;/ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

Interface SomeObject Extends SomeObject::Public
EndInterface

box.BoxObject=BoxObject::new()

;/ BoxObject has default values
Debug box\getHeight()
Debug box\getWidth()

obj.SomeObject=SomeObject::new()

;/ SomeObject has a BoxObject which has dimensions
Debug obj\getBox()\ ; <- Can't do it


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Mon Jul 16, 2018 3:16 am 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
This is interesting and you would think that it might work but it does not:

Code:
Interface BoxObject
EndInterface

Structure SomeObject
  getBox.BoxObject
EndStructure

*obj.SomeObject=0

; [Error] Garbage at the end of the line.
Debug *obj\getBox() ; <- Can't do it


It seems like a hard limitation that we can't call functions in this way.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Mon Jul 16, 2018 7:34 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
Mistrel wrote:
This is interesting and you would think that it might work but it does not:

Code:
Interface BoxObject
EndInterface

Structure SomeObject
  getBox.BoxObject
EndStructure

*obj.SomeObject=0

; [Error] Garbage at the end of the line.
Debug *obj\getBox() ; <- Can't do it


It seems like a hard limitation that we can't call functions in this way.


Heres a working example:
Code:
Interface BoxObject
  GetBox.i()
EndInterface

Structure SomeObject
  *getBox.BoxObject
EndStructure

Global *obj.SomeObject

Procedure.i GetBox(*VT)
  Debug "Something"
EndProcedure

Procedure.i GetInterface()
  Protected *Interface, *Set.Integer
  *Interface = AllocateMemory(SizeOf(Integer) * 2)
  If *Interface
    *Set = *Interface:*Set\i = *Interface + SizeOf(Integer)
    *Set + SizeOf(Integer):*Set\i = @GetBox();<- the inteface will have one function
  EndIf
  ProcedureReturn *Interface
EndProcedure

*obj = AllocateStructure(SomeObject);<- structure needs to be allocated
*obj\getBox = GetInterface();<- assign a interface
*obj\getBox\GetBox();<- call it


A interface always needs a vtable you cant use it without.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Mon Jul 16, 2018 5:40 pm 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2683
Location: Germany
@Mistrel

You're a little lost now.
I've now rebuilt my example the way you need it.

Unfortunately Purebasic cannot do this:
Code:
r1 = *obj1\GetBox()\GetWidth()

What Mijikai means, I called at the bottom of the test.

Example Update 1.6
Code:
;-TOP

; Example 1.6

; ***************************************************************************************

DeclareModule Public
 
  Interface iDefault
    Addref()
    Release()
  EndInterface
 
  Structure sDefault
    *vTable.iDefault
    Refcounter.i
  EndStructure
 
EndDeclareModule

Module Public
 
EndModule


; ***************************************************************************************

DeclareModule BoxObject
 
  Interface iBoxObject Extends Public::iDefault
    GetWidth()
    GetHeiht()
  EndInterface
 
  Declare New()
 
EndDeclareModule

Module BoxObject
 
  Structure sBoxObject Extends Public::sDefault
    dx.i
    dy.i
  EndStructure
 
  Procedure Addref(*this.sBoxObject)
    With *this
      \Refcounter + 1
      Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Addref - Refcounter: " + \Refcounter
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure Release(*this.sBoxObject)
    With *this
      If \Refcounter = 0
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Destroy - Refcounter: " + \Refcounter
        FreeStructure(*this)
      Else
        \Refcounter - 1
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Release - Refcounter: " + \Refcounter
      EndIf
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure GetWidth(*this.sBoxObject)
    With *this
      ProcedureReturn \dx
    EndWith
  EndProcedure
 
  Procedure GetHeight(*this.sBoxObject)
    With *this
      ProcedureReturn \dy
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  Procedure New()
    Protected *this.sBoxObject
    With *this
      *this = AllocateStructure(sBoxObject)
      If *this
        \vTable = ?vtBoxObject
        \Refcounter = 0
        \dx = Random(400, 100)
        \dy = Random(300, 10)
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " New - Refcounter: " + \Refcounter
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  DataSection
    vtBoxObject:
    Data.i @Addref()
    Data.i @Release()
    Data.i @GetWidth()
    Data.i @GetHeight()
  EndDataSection
 
EndModule

; ***************************************************************************************

DeclareModule CircleObject
 
  Interface iCircleObject Extends Public::iDefault
    GetRadius()
  EndInterface
 
  Declare New()
 
EndDeclareModule

Module CircleObject
 
  Structure sCircleObject Extends Public::sDefault
    r.i
  EndStructure
 
  Procedure Addref(*this.sCircleObject)
    With *this
      \Refcounter + 1
      Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Addref - Refcounter: " + \Refcounter
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure Release(*this.sCircleObject)
    With *this
      If \Refcounter = 0
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Destoy - Refcounter: " + \Refcounter
        FreeStructure(*this)
      Else
        \Refcounter - 1
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Release - Refcounter: " + \Refcounter
      EndIf
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure GetRadius(*this.sCircleObject)
    With *this
      ProcedureReturn \r
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  Procedure New()
    Protected *this.sCircleObject
    With *this
      *this = AllocateStructure(sCircleObject)
      If *this
        \vTable = ?vtCircleObject
        \Refcounter = 0
        \r = Random(400, 100)
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " New - Refcounter: " + \Refcounter
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  DataSection
    vtCircleObject:
    Data.i @Addref()
    Data.i @Release()
    Data.i @GetRadius()
  EndDataSection
 
EndModule

; ***************************************************************************************


; ***************************************************************************************

DeclareModule MyObject
 
  Interface iMyObject Extends Public::iDefault
    GetBox()
    GetCircle()
  EndInterface
 
  Structure sMyObject Extends Public::sDefault
    *Self.iMyObject
    *Box.BoxObject::iBoxObject
    *Circle.CircleObject::iCircleObject
  EndStructure
 
  Declare New()
 
EndDeclareModule

Module MyObject
 
  Procedure Addref(*this.sMyObject)
    With *this
      \Refcounter + 1
      Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Addref - Refcounter: " + \Refcounter
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure Release(*this.sMyObject)
    With *this
      If \Refcounter = 0
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Destoy - Refcounter: " + \Refcounter
        \Box\Release()
        \Circle\Release()
        FreeStructure(*this)
      Else
        \Refcounter - 1
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " Release - Refcounter: " + \Refcounter
      EndIf
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure GetBox(*this.sMyObject)
    With *this
      \Box\Addref()
      ProcedureReturn \Box
    EndWith
  EndProcedure
 
  Procedure GetCircle(*this.sMyObject)
    With *this
      \Circle\Addref()
      ProcedureReturn \Circle
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  Procedure New()
    Protected *this.sMyObject
    With *this
      *this = AllocateStructure(sMyObject)
      If *this
        Debug "[" + Hex(*this) + "] " + #PB_Compiler_Module + " New - Refcounter: " + \Refcounter
        \vTable = ?vtMyObject
        \Self = *this
        \Box = BoxObject::New()
        \Circle = CircleObject::New()
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  DataSection
    vtMyObject:
    Data.i @Addref()
    Data.i @Release()
    Data.i @GetBox()
    Data.i @GetCircle()
  EndDataSection
 
EndModule

; ***************************************************************************************

;- Test

Define.MyObject::iMyObject *obj1
Define.BoxObject::iBoxObject *box1
Define.CircleObject::iCircleObject *Circle1

Debug "New MyObject..."
*obj1 = MyObject::New()

Debug "Get Box 1"
*box1 = *obj1\GetBox()
Debug "DX: " + *box1\GetWidth()
Debug "DY: " + *box1\GetHeiht()

Debug "Get Circle 1"
*Circle1 = *obj1\GetCircle()
Debug "R : " + *Circle1\GetRadius()

Debug "Release box 1"
*box1\Release()
*Circle1\Release()

Debug "Release obj 1"
*obj1\Release()

Debug "This is not possible because purebasic cannot resolve the object chain."
;r1 = *obj1\GetBox()\GetWidth()

Debug "Trick... but not good"
Define *obj2.MyObject::sMyObject
*obj2 = MyObject::New()
Debug "DX: " + *obj2\Box\GetWidth()
Debug "R : " + *obj2\Circle\GetRadius()

Debug "Release obj "
*obj2\Self\Release()

_________________
My Projects ThreadToGUI / OOP-BaseClass / OOP-BaseClassDispatch / EventDesigner V3
PB v3.30 / v5.70 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Wed Oct 16, 2019 3:23 am 
Offline
User
User

Joined: Mon Feb 26, 2018 3:14 am
Posts: 12
Hmm would this style of organization help you? Maybe it's a bit much but if i were wanting to make a work around it maybe something close to this. Note: This was quick coding so i didn't add any memory freeing management.
I am trying to show some of the possible flexibility and alternative methods all in one :D .


Code:
DeclareModule world
  Interface _
    getwidth()
    getheight()
   
  EndInterface
 
 
  Interface Main_Methods
    ShowBoxes()
    newbox(Name$,x,y,width,height)
  EndInterface
  Structure box
    *interface
    x.l
    y.l
    width.l
    height.l
  EndStructure
 
  Structure main
    *interface
    Map *Box._()
  EndStructure
 
 
  Structure NewObject
    *Functions.Main_Methods
    *Vars.main
  EndStructure
 
 
  Declare create()
EndDeclareModule



Module world
 
  Procedure create()
    *new.main = AllocateStructure(main)
    *new\interface = ?Main_Methods
    *object.NewObject = AllocateStructure(NewObject)
    *object\Functions = *new
    *object\Vars = *new
   
     ProcedureReturn *object
   
  EndProcedure
 
 
  Procedure NewBox(*self.main,Name$,x,y,width,height)
    With *self
       AddMapElement(\Box(),name$)
       
      *this.box = AllocateStructure(box)
       *this\x = x
      *this\y = y
      *this\width = width
      *this\height = height
      *this\interface = ?Box_Methods
      \Box() = *this
    EndWith
  EndProcedure
 
  Procedure showboxes(*self.main)
    Debug "name: x,y,width,height"
    ForEach *self\Box()
      *this.box = *self\Box()
      Debug MapKey(*self\Box()) + ":" + Str(*this\x) + "," + Str(*this\y) + "," + Str(*this\width) + "," + Str(*this\height)
   Next
  EndProcedure
 
 
 
  Procedure GetWidth(*self.box)
    ProcedureReturn *self\width
  EndProcedure
 
  Procedure getheight(*self.box)
    ProcedureReturn *self\height
  EndProcedure
 
  DataSection
    Main_Methods:
    Data.i @showboxes(),@newbox()
    Box_Methods:
    Data.i @getwidth(),@getheight()
  EndDataSection
 
EndModule


*Galaxy.world::NewObject = world::create()

*Galaxy\Functions\newbox("Small",0,0,10,10)
*Galaxy\Functions\newbox("Medium",0,0,100,100)
*Galaxy\Functions\newbox("Large",0,0,1000,1000)
*Galaxy\Functions\newbox("Random",Random(1000),Random(1000),Random(1000),Random(1000))
*Galaxy\Functions\ShowBoxes()

Debug "Large Width:" + Str(*Galaxy\Vars\Box("Large")\getwidth())


Debug ""
Debug "Lets get all the heights"
ForEach *Galaxy\Vars\Box()
  Debug MapKey(*Galaxy\Vars\Box()) + "::" + "Height = " + Str(*Galaxy\Vars\Box()\getheight())
Next


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page Previous  1, 2

All times are UTC + 1 hour


Who is online

Users browsing this forum: Jeff8888, Olli and 60 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye