It is currently Fri Oct 30, 2020 5:04 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: How to call methods from the result of another interface?
PostPosted: Sat Jul 14, 2018 6:39 am 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
I'm just not starting to move to object-oriented programming in PureBasic to make my code more consistent and portable between the languages I use. I've spent a lot of time getting familiar with how to make things work but this one is stumping me.

If I have an interface method which returns an instance of another object, how do I declare things such that I can call them in sequence?

For example:

Code:
DeclareModule SomeObject
  Interface BoxObject
    getWidth()
    getHeight()
  EndInterface
 
  Interface Public
    ;/ [Error] A structure can't be used with ProcedureReturn.
    ;getBox.BoxObject()
    getBox()
  EndInterface
 
  Declare new()
EndDeclareModule

Module SomeObject
  Procedure new()
  EndProcedure
EndModule

Interface SomeObject Extends SomeObject::Public
EndInterface

obj.SomeObject=SomeObject::new()

;/ [Error] Garbage at the end of the line.
Debug obj\getBox()\getWidth()


I'm returning a reference to an interface. Assigning a reference to a variable declared as an interface works but not for methods within an interface?

Why can't I do this?

Code:
;/ Allowed
obj.SomeObject=*instance

;/ Not allowed?
Procedure.SomeObject ProcA()
  ProcedureReturn *instance
EndProcedure


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sat Jul 14, 2018 9:37 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Jun 22, 2003 7:43 pm
Posts: 619
Location: Germany, Saarbrücken
This ist not possible but it exists a feature request to make it possible.

_________________
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sat Jul 14, 2018 9:57 am 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
If this cannot be done then interfaces in PureBasic is toothless.

I was really looking forward to porting some object-oriented code but now I'll have to rewrite a large portion of it.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sat Jul 14, 2018 10:24 am 
Offline
Addict
Addict
User avatar

Joined: Fri May 12, 2006 6:51 pm
Posts: 2687
Location: Germany
Purebasic supports the OOP calling convention.
Not the automatic splitting of calling OOP chains.

In your example, the'GetBoxObject' is missing

The correct sequence is therefore

obj.InterfaceSomeObject = NewSomeObject()
obj2.InterfaceBoxObject =obj\GetBoxObject()
r1 = obj2\GetWidth()
r2 = obj2\GetHeight()
obj2\Release()
obj\Release()

My OOP-BaseClass modules are examples of this.

_________________
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: Sat Jul 14, 2018 11:25 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
How about:
Code:
Structure INTERFACE_STRUCT
  StructureUnion
    *Interface.iPublic
    *VT.PUBLIC_VTABLE_STRUCT;the vtable gets modified to contain iObject -> *Object.iObject!
  EndStructureUnion
EndStructure


That allows you to assing or return a interface:
Code:
Global Public.INTERFACE_STRUCT
;...
Public\Interface = InterfacePublic();make a iPublic interface with custom vtable
Public\VT\Object = *Object;pointer to any iObject interface


Then use the VTable to call it:
Code:
Public\VT\Object\Message()


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sat Jul 14, 2018 12:23 pm 
Offline
Addict
Addict

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
I don't think a structure union would work if the public interface does not align with the vtable.


Top
 Profile  
Reply with quote  
 Post subject: Re: How to call methods from the result of another interface
PostPosted: Sat Jul 14, 2018 12:32 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
Mistrel wrote:
I don't think a structure union would work if the public interface does not align with the vtable.


The structure will expand to the size of the modified (extended) vtable.

This is also possible:
Code:
Interface iPublic
  Something.i()
EndInterface

;...

Procedure.i Something(*VT.PUBLIC_VTABLE_STRUCT)
  ProcedureReturn *VT\Object\Message()
EndProcedure

A interface function (Something()) of the public interface accesses the supplied
Object interface through the expanded vtable.


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

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
I've looked at this more closely. Wouldn't it result in an additional VT field for every object in the call chain? :|

Code:
Object\VT\getA\VT\getB\VT\getC()


Compared to:

Code:
Object\getA()\getB()\getC()


There's also no way to pass arguments in the call chain except to the last method.


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

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
Mistrel wrote:
I've looked at this more closely. Wouldn't it result in an additional VT field for every object in the call chain? :|

Code:
Object\VT\getA\VT\getB\VT\getC()


Compared to:

Code:
Object\getA()\getB()\getC()


There's also no way to pass arguments in the call chain except to the last method.


I dont see why writing out the calls would be a problem.
Wont it get also messy if you write several calls in one line?


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

Joined: Sat Jun 30, 2007 8:04 pm
Posts: 3371
Say I have a world object of players and want to teleport one to 0,0,0.

Code:
world\getPlayer("Bugsy22")\teleport(0,0,0)


I can't chain these as per your workaround because:

Code:
world\getPlayer("Bugsy22")\ <- this is an interface and I can't access additional members


It has the same problem as my original post. Using the interface/vtable union is only a partial workaround and brings with it a different problem:

Code:
world\getPlayer\ <- this is pointer to a structure and I can't pass arguments


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

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
I dont rly see the problem...
Code:
Public\Interface\GetPlayer("Bugs");<- will get the interface and pass it to the vtable
Public\VT\Teleport(0,0,0);<- will call the function of the passed interface


Make the structure available in the passed vtable and you can use
a function to mess with it or just use it directly.


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

Joined: Fri May 12, 2006 6:51 pm
Posts: 2687
Location: Germany
You have forgotten something essential with the handling of interfaces and objects.
Calling a function in a subobject is not enough.

Wrote about an example of what the process must be like.
Code:
;-TOP

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

DeclareModule MyObject
 
  Interface iBoxObject
    Release()
    GetWidth()
    GetHeiht()
  EndInterface
 
  Interface iMyObject
    Release()
    GetBox()
  EndInterface
 
  Declare New()
 
EndDeclareModule

Module MyObject
 
  Structure sMyObject
    *vTable
    BoxObject.iBoxObject
  EndStructure
 
  Structure sBoxObject
    *vTable
    Refcounter.i
    dx.i
    dy.i
  EndStructure
 
  Procedure Box_Release(*this.sBoxObject)
    With *this
      If \Refcounter = 0
        Debug "[" + Hex(*this) + "] Box destoy object refcounter: " + \Refcounter
        FreeStructure(*this)
      Else
        Debug "[" + Hex(*this) + "] Box release object refcounter: " + \Refcounter
        \Refcounter - 1
      EndIf
      ProcedureReturn \Refcounter
    EndWith
  EndProcedure
 
  Procedure Box_GetWidth(*this.sBoxObject)
    With *this
      ProcedureReturn \dx
    EndWith
  EndProcedure
 
  Procedure Box_GetHeight(*this.sBoxObject)
    With *this
      ProcedureReturn \dy
    EndWith
  EndProcedure
 
  Procedure Box_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) + "] Box new object refcounter: " + \Refcounter
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  Procedure Box_GetObject(*this.sBoxObject)
    With *this
      \Refcounter + 1
      Debug "[" + Hex(*this) + "] Box get object refcounter: " + \Refcounter
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  Procedure Release(*this.sMyObject)
    With *this
      Box_Release(\BoxObject)
      FreeStructure(*this)
    EndWith
  EndProcedure
 
  Procedure GetBox(*this.sMyObject)
    With *this
      ProcedureReturn Box_GetObject(\BoxObject)
    EndWith
  EndProcedure
 
  ; -----------------------------------------------------------------
 
  Procedure New()
    Protected *this.sMyObject
    With *this
      *this = AllocateStructure(sMyObject)
      If *this
        \vTable = ?vtMyObject
        \BoxObject = Box_New()
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
 
  DataSection
    vtBoxObject:
    Data.i @Box_Release()
    Data.i @Box_GetWidth()
    Data.i @Box_GetHeight()
   
    vtMyObject:
    Data.i @Release()
    Data.i @GetBox()
  EndDataSection
 
EndModule

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

;- Test

Define.MyObject::iMyObject *obj1, *obj2
Define.MyObject::iBoxObject *box1, *box2

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

Debug "Get Object 1"
*box1 = *obj1\GetBox()
Debug *box1\GetWidth()
Debug *box1\GetHeiht()


Debug "Get Object 2"
*box2 = *obj2\GetBox()
Debug *box2\GetWidth()
Debug *box2\GetHeiht()

Debug "Relases box 1"
*box1\Release()
Debug "Relases obj 1"
*obj1\Release()
Debug "Relases box 2"
*box2\Release()
Debug "Relases obj 2"
*obj2\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: Sun Jul 15, 2018 11:51 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
mk-soft wrote:
You have forgotten something essential with the handling of interfaces and objects.
Calling a function in a subobject is not enough.
...


I cant follow you - the solution i proposed does not change the interface itself
but extends the underlinig vtable by adding stuff but not by changing it.


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

Joined: Fri May 12, 2006 6:51 pm
Posts: 2687
Location: Germany
Unfortunately, there are also rules in the programming.
A deviation in this range definitely leads to errors and is not supported by the compiler.

The call you're trying doesn't go like this...

Maybe someone who speaks better English can discuss this again.


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()}

Purebasic is not OOP, but supports the Object Rules

P.P.S
If you want to see what happens when objects are called up, check out my project 'OOP-BaseClassDispatch'.
This can write log files...

_________________
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: Sun Jul 15, 2018 12:52 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Sep 11, 2016 2:17 pm
Posts: 732
mk-soft wrote:
Unfortunately, there are also rules in the programming.
A deviation in this range definitely leads to errors and is not supported by the compiler.

The call you're trying doesn't go like this...



So i cant call a function provided by a interface in a structure?
And a structure should not hold more than just the vtable?

Im sorry i dont get it mby its a english barrier.


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

All times are UTC + 1 hour


Who is online

Users browsing this forum: Tawbie and 47 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