Prozedur in Variable speichern

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
4Planes
Beiträge: 37
Registriert: 19.11.2020 17:08

Re: Prozedur in Variable speichern

Beitrag von 4Planes »

Das dein Beispiel funktioniert heißt leider nicht, dass es richtig ist.
Das ist ein wahrer Satz, der auf Vieles im Leben zutrifft.

Trotzdem will ich nochmal nachbohren: Sagst du in dem Post, den du verlinkt hast, nicht selber, dass das funktionieren sollte?
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Prozedur in Variable speichern

Beitrag von STARGÅTE »

4Planes hat geschrieben:
Trotzdem will ich nochmal nachbohren: Sagst du in dem Post, den du verlinkt hast, nicht selber, dass das funktionieren sollte?
Jup, es funktioniert (scheinbar). Aber Trial and Error ist beim sauberen Programmieren fehl am Platz. Es ist gefährlich so etwas, was nicht offiziell von PureBasic "erlaubt" wird, zumindest habe ich dazu nichts in der Hilfe gefunden, in einem Programm zu nutzen.
Denn es sind später genau diese "Tricks" die vielleicht irgendwann in einem großen Projekt zu einem unerklärlichen Fehler führen, wo die Ursachenforschung dann sehr mühsam ist.
Ich kann von meiner Seite sagen, dass ich diese Möglichkeit nicht nutze, sondern je nach Situation genau die richtige Prozedur aufrufe mit der richtigen Anzahl von Parametern
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Prozedur in Variable speichern

Beitrag von mk-soft »

Wenn die Prototype richtig angelegt sind, Anzahl der Parameter und Parameter Typen stimmen, wenn auch die Procedure Adresse richtig zuwiesen ist, funktioniert dieses sicher.

In irgendeiner Beta Version von Purebasic ging plötzlich der Aufruf über die virtuelle Tabelle nicht mehr. Wurde aber sofort nach Meldung des Bugs sofort repariert.

Zum Beispiel:
Bei OOP-BaseClass werden Arrays verwendet um die Methoden in der virtuellen Tabelle zu hinterlegen.
Im EventDesigner V3 werden die Event Proceduren in der DataSection als virtuelle Tabelle hinterlegt und über ein Index (EventMenu, EventGadget) aufgerufen.

Beispiel GuiEventMainFile

Code: Alles auswählen

;-TOP

; ***************************************************************************
; 
; Comment : EventDesigner - Common Event Main File
; Create  : 2020.12.03 14.22.42
; 
; Info    : Do not edit this file. This file always overwrite.
; 
; ***************************************************************************

; - Include Event Files
IncludeFile "GuiEventcommon.pb"

; ----

Prototype _MyPrototypeInvoke()

Structure _MyEventInvoke
  Invoke._MyPrototypeInvoke[0]
EndStructure

Global *vtMyEventSizeWindow._MyEventInvoke = ?vtMyEventSizeWindow
Global *vtMyEventCloseWindow._MyEventInvoke = ?vtMyEventCloseWindow
Global *vtMyEventMenu._MyEventInvoke = ?vtMyEventMenu
Global *vtMyEventGadget._MyEventInvoke = ?vtMyEventGadget

#MyEventCountWindow = 1
#MyEventCountMenu = 2
#MyEventCountGadget = 4

; ----

Procedure _MyEventSizeWindow()
  Protected WindowID = EventWindow()
  Select WindowID
    Case 0 To #MyEventCountWindow - 1
      *vtMyEventSizeWindow\Invoke[WindowID]()
  EndSelect
EndProcedure

; ----

Procedure _MyEventCloseWindow()
  Protected WindowID = EventWindow()
  Select WindowID
    Case 0 To #MyEventCountWindow - 1
      *vtMyEventCloseWindow\Invoke[WindowID]()
  EndSelect
EndProcedure

; ----

Procedure _MyEventMenu()
  Protected MenuID = EventMenu()
  Select MenuID
    Case 0 To #MyEventCountMenu - 1
      *vtMyEventMenu\Invoke[MenuID]()
  EndSelect
EndProcedure

; ----

Procedure _MyEventGadget()
  Protected GadgetID = EventGadget()
  Select GadgetID
    Case 0 To #MyEventCountGadget - 1
      *vtMyEventGadget\Invoke[GadgetID]()
  EndSelect
EndProcedure

; ----

Procedure _MyEventGadgetNothing()
  ; Do Nothing
EndProcedure

; ----

; - Bind Events
BindEvent(#PB_Event_Menu, @_MyEventMenu())
BindEvent(#PB_Event_Gadget, @_MyEventGadget())
BindEvent(#PB_Event_SizeWindow, @_MyEventSizeWindow())
BindEvent(#PB_Event_CloseWindow, @_MyEventCloseWindow())
    
; ----

DataSection
  vtMyEventSizeWindow:
  Data.i @MyEventSizeWindow_WinMain()
  
  vtMyEventCloseWindow:
  Data.i @MyEventCloseWindow_WinMain()
  
  vtMyEventMenu:
  Data.i @MyEventMenu_WinMain_MenuItem_Dialog()
  Data.i @MyEventMenu_WinMain_MenuItem_Exit()
  
  vtMyEventGadget:
  Data.i @MyEventGadget_WinMain_Button_DoYes()
  Data.i @MyEventGadget_WinMain_Button_DoCancel()
  Data.i @_MyEventGadgetNothing()
  Data.i @MyEventGadget_WinMain_Calendar()
  
EndDataSection

; ----
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
juergenkulow
Beiträge: 188
Registriert: 22.12.2016 12:49
Wohnort: :D_üsseldorf-Wersten

Re: Prozedur in Variable speichern

Beitrag von juergenkulow »

Hallo,

Code: Alles auswählen

; Aufrufe aus einem Feld von Proceduren mit einem Pointer als Parameter 

Prototype.i MyProcedure(*Param)
Procedure.i VersionPtr1(*Param)       
  Debug "1. Version Ptr:"     +*Param
  ProcedureReturn *Param
EndProcedure

Procedure.i VersionPtr2(*Param)       
  Debug "2. Version Ptr:"     +*Param
  ProcedureReturn *Param
EndProcedure

Structure Item : Proc.MyProcedure : EndStructure
Dim AufrufFeldPtr.Item(10)
For i=0 To 10 
  If 1=Random(2,1)
    AufrufFeldPtr(i)\Proc=@VersionPtr1() 
  Else 
    AufrufFeldPtr(i)\Proc=@VersionPtr2()
  EndIf 
Next
*myptr=AllocateMemory(12345)
For i=0 To 10 
  ret=AufrufFeldPtr(i)\Proc(*myptr)
  Debug ret 
Next

; ; ret=AufrufFeldPtr(i)\Proc(*myptr)
;   MOV    r15,qword [v_i]
;   MOV    rbp,qword [a_AufrufFeldPtr]
;   SAL    r15,3
;   ADD    rbp,r15
;   PUSH   qword [rbp]
;   SUB    rsp,8
;   PUSH   qword [p_myptr]
;   POP    rdi
;   CALL   qword [rsp+8]
;   ADD    rsp,8
;   ADD    rsp,8
;   MOV    qword [v_ret],rax

Code: Alles auswählen

; Aufrufe mit verschiedenen Parametertypen unter Linux x64 
; ; VersionDouble(12.345)
;   PUSH   qword [D1]
;   MOVSD  xmm0,qword [rsp]
;   ADD    rsp,8
;   CALL  _Procedure0
; ; VersionFloat(12.345)
;   FLD    dword [F1]
;   SUB    rsp,8
;   FSTP   dword [rsp]
;   MOVSS  xmm0,dword [rsp]
;   ADD    rsp,8
;   CALL  _Procedure4
; ; VersionString("12.345")
;   MOV    rax,_S1
;   PUSH   rax
;   POP    rdi
;   CALL  _Procedure6
; ; VersionLong(12345)
;   MOV    rax,12345
;   MOV    rax,rax
;   PUSH   rax
;   POP    rdi
;   CALL  _Procedure8
; ; VersionQuad(12345)
;   PUSH   qword 12345
;   POP    rdi
;   CALL  _Procedure10
; ; VersionPtr(12345)
;   PUSH   qword 12345
;   POP    rdi
;   CALL  _Procedure12
Antworten