Assigning structure address to Interface invalid memory access error

Just starting out? Need help? Post your questions and find answers here.
devox
User
User
Posts: 24
Joined: Thu Apr 01, 2021 7:25 pm
Location: Albion

Assigning structure address to Interface invalid memory access error

Post by devox »

Hi,

I'm experimenting with some of the OOP like features in PB, and I'm following Drac's tutorials on the subject (http://drac.site.chez-alice.fr/Tutorial ... ace_en.htm).

I have this basic bit of code

Code: Select all

Interface IPerson
  Display()
EndInterface

Structure PersonMethods
  *Display
EndStructure

Procedure Person_Display()
  Debug "Display Called"
EndProcedure

PersonImp.PersonMethods
PersonImp\Display = @Person_Display()

Debug "Calling Display() using Implementation pointer"
CallFunctionFast(PersonImp\Display)

Debug ""

Person.IPerson = @PersonImp
Debug "Calling Display() using Interface"
Person\Display()
But when I run it the last call on Person\Display() causes a runtime error of invalid memory address? I am able to call the method via CallFunctionFast with the function pointer though?
User avatar
Bisonte
Addict
Addict
Posts: 1163
Joined: Tue Oct 09, 2007 2:15 am

Re: Assigning structure address to Interface invalid memory access error

Post by Bisonte »

Here is a "skeleton" for using own interfaces I'am using (edit it for your test person):

Code: Select all

DeclareModule Person
  
  EnableExplicit
  
  Interface iPerson
    SetName(Name.s)
    GetName.s()
    SetAge(Age)
    GetAge()
    Display()
    Destroy()  
  EndInterface
  
  Declare.i CreatePerson(Name.s)
  
EndDeclareModule
Module        Person
  
  Structure obj
    vTable.i ; virtual table must be the first entry !!
    Name.s
    Age.i
  EndStructure

  ; -- Methods
  ; =============================================================================  
  
  Procedure.i SetName(*this.obj, Name.s)
    
    If *this
      *this\Name = Name  
    EndIf
    
  EndProcedure
  Procedure.s GetName(*this.obj)
    
    Protected Result.s = ""
    
    If *this
      Result = *this\Name
    EndIf
    
    ProcedureReturn Result
    
  EndProcedure
  Procedure.i SetAge(*this.obj, Age)
    
    If *this
      *this\Age = Age  
    EndIf
    
  EndProcedure
  Procedure.i GetAge(*this.obj)
    
    Protected Result.i
    
    If *this
      Result = *this\Age
    EndIf
    
    ProcedureReturn Result
    
  EndProcedure
  Procedure.i Display(*this.obj)
    
    If *this
      Debug "Person Data"
      Debug "-----------"
      Debug "Name : " + *this\Name
      Debug "Age  : " + *this\Age
      Debug "==========="
    EndIf
    
  EndProcedure
  
  Procedure.i DestroyObject(*this.obj)
 
    FreeStructure(*this) : *this = #Null
    ProcedureReturn *this
    
  EndProcedure
  

  ; -- Public
  
  Procedure.i CreatePerson(Name.s)
    
    Protected *this.obj = AllocateStructure(obj)
    
    If *this
      
      *this\vTable = ?vTable_iPerson
      *this\Name = Name
      
    EndIf
    
    ProcedureReturn *this
        
  EndProcedure  

  ; -- Virtual Table
  ; =============================================================================  
  ; the order of the Methods must be the same like in Interface-EndInterface !
  DataSection
    vTable_iPerson:
    Data.i @SetName()
    Data.i @GetName()
    Data.i @SetAge()
    Data.i @GetAge()
    Data.i @Display()
    Data.i @DestroyObject()    
  EndDataSection
  
EndModule
UseModule     Person

; Demo

Person1.iPerson = CreatePerson("Devox")

Person1\SetAge(20)

Person1\Display()

Person1\Destroy()
In your example you can only use Methods without parameters... and Callfunction... you should not use it, because it is very error-prone !
Prototype is the keyword for search in PB-Manual, if you want to use CallFunction or CallFunctionFast ...
PureBasic 5.73 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
devox
User
User
Posts: 24
Joined: Thu Apr 01, 2021 7:25 pm
Location: Albion

Re: Assigning structure address to Interface invalid memory access error

Post by devox »

@Bisonte, thank you very much that is extremely helpful. :thumbsup:
User avatar
Bisonte
Addict
Addict
Posts: 1163
Joined: Tue Oct 09, 2007 2:15 am

Re: Assigning structure address to Interface invalid memory access error

Post by Bisonte »

The examples from mk-soft helped me a lot... Thanks go to him ;)
PureBasic 5.73 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
User avatar
StarBootics
Enthusiast
Enthusiast
Posts: 717
Joined: Sun Jul 07, 2013 11:35 am
Location: Canada

Re: Assigning structure address to Interface invalid memory access error

Post by StarBootics »

devox wrote: Fri Apr 23, 2021 12:33 pm Hi,

I'm experimenting with some of the OOP like features in PB, and I'm following Drac's tutorials on the subject (http://drac.site.chez-alice.fr/Tutorial ... ace_en.htm).
It's a very old sets of tutorials. That being said if you want to really experiment some OOP with PureBasic I suggest to download, study and compile for your self Dev-Object that can write code like that in matter of milliseconds. For example :

Code: Select all

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; AUTOMATICALLY GENERATED CODE, DO NOT MODIFY
; UNLESS YOU REALLY, REALLY, REALLY MEAN IT !!
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Code generated by : Dev-Object - V1.4.5
; Project name : the project name here
; File name : File name here
; File Version : 0.0.0
; Programmation : In progress
; Programmed by : StarBootics
; Creation Date : 23-04-2021
; Last update : 23-04-2021
; Coded for PureBasic : V5.73 LTS
; Platform : Windows, Linux, MacOS X
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

DeclareModule Person
  
  Interface Person
    
    GetName.s()
    GetAge.l()
    SetName(P_Name.s)
    SetAge(P_Age.l)
    Update(P_Name.s, P_Age.l)
    Reset()
    Copy.i()
    Free()
    
  EndInterface
  
  ; Declare Free(*This)
  Declare.i New(P_Name.s = "", P_Age.l = 0)
  
EndDeclareModule

Module Person
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< Structure declaration <<<<<

  Structure Private_Members
    
    VirtualTable.i
    Name.s
    Age.l
    
  EndStructure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The observators <<<<<

  Procedure.s GetName(*This.Private_Members)
    
    ProcedureReturn *This\Name
  EndProcedure
  
  Procedure.l GetAge(*This.Private_Members)
    
    ProcedureReturn *This\Age
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The mutators <<<<<

  Procedure SetName(*This.Private_Members, P_Name.s)
    
    *This\Name = P_Name
    
  EndProcedure
  
  Procedure SetAge(*This.Private_Members, P_Age.l)
    
    *This\Age = P_Age
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Update operator <<<<<

  Procedure Update(*This.Private_Members, P_Name.s, P_Age.l)
    
    *This\Name = P_Name
    *This\Age = P_Age
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Reset operator <<<<<

  Procedure Reset(*This.Private_Members)
    
    *This\Name = ""
    *This\Age = 0
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Copy operator <<<<<

  Procedure.i Copy(*This.Private_Members)
    
    *Copy.Private_Members = AllocateStructure(Private_Members)
    *Copy\VirtualTable = ?START_METHODS
    
    *Copy\Name = *This\Name
    *Copy\Age = *This\Age
    
    ProcedureReturn *Copy
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Destructor <<<<<

  Procedure Free(*This.Private_Members)
    
    FreeStructure(*This)
    
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Constructor <<<<<

  Procedure.i New(P_Name.s = "", P_Age.l = 0)
    
    *This.Private_Members = AllocateStructure(Private_Members)
    *This\VirtualTable = ?START_METHODS
    
    *This\Name = P_Name
    *This\Age = P_Age
    
    ProcedureReturn *This
  EndProcedure
  
  ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  ; <<<<< The Virtual Table Entries <<<<<

  DataSection
    START_METHODS:
    Data.i @GetName()
    Data.i @GetAge()
    Data.i @SetName()
    Data.i @SetAge()
    Data.i @Update()
    Data.i @Reset()
    Data.i @Copy()
    Data.i @Free()
    END_METHODS:
  EndDataSection
  
EndModule

; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; <<<<< Code generated in : 00.001 seconds (154000.00 lines/second) <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

; <<<<<<<<<<<<<<<<<<<<<<<
; <<<<< END OF FILE <<<<<
; <<<<<<<<<<<<<<<<<<<<<<<
Best regards
StarBootics
The Stone Age did not end due to a shortage of stones !
devox
User
User
Posts: 24
Joined: Thu Apr 01, 2021 7:25 pm
Location: Albion

Re: Assigning structure address to Interface invalid memory access error

Post by devox »

StarBootics wrote: Sat Apr 24, 2021 2:40 am It's a very old sets of tutorials. That being said if you want to really experiment some OOP with PureBasic I suggest to download, study and compile for your self Dev-Object that can write code like that in matter of milliseconds.
I had a feeling what I was doing maybe out of date, found that problem a few times whilst learning PB. Your tool looks just brilliant and really helpful with this I will be sure to give it a try.

Many thanks
User avatar
mk-soft
Addict
Addict
Posts: 3201
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Assigning structure address to Interface invalid memory access error

Post by mk-soft »

If you then start with external interfaces (Windows COM Objects), that the parameter passing and just the return of the result of a method looks a little different.

The result of a method is then always whether the method was successfully executed and for the return value a pointer must be passed in the parameter.

If you are interested, you can also have a look at OOP-BaseClass and, if you are ready, at OOP-BaseClassDispatch for creating DLLs externally.
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
Post Reply