Danke nochmal an euch alle drei!
Meine Wissenslücken sind nun soweit geschlossen, dass ich "kritische Stellen" im aktuellen Projekt prüfen und korrigieren kann! Habe sogar noch etwas darüber hinaus gelernt.
Das einzige was mir noch nicht ganz klar ist, ist dass ich zwar mehrfach gelesen habe, dass "Pointer-Sternchen" und "Dereferrer-Operator-Sternchen" zwei total unterschiedliche Dinge sind und dass man die nur nicht durcheinander bringen soll. Aber WAS der Unterschied sein soll konnte ich nicht erkennen... oder ist da einfach nur zum einen das Sternchen bei der Zeigerdeklaration und zum anderen das Sternchen im Code (z.B. bei einer Zuweisung) gemeint? Wenn ja, dann hätte ich's doch verstanden...
Gut zu wissen! Ja, das Original sfxr ist in eigentlich C++, allerdings hatte ich nur C-Code ausmachen können. In C++ kann ich nicht programmieren, sonder nur (manchmal mit einiger Mühe) Code-Beispiele nachvollziehen, wie Sie hier im Board ja auch ab und zu mal verlinkt werden.
Danilo hat geschrieben:Mit Pelles C oder LCCwin32/64 könntest Du ja lauffähige Codes machen,
die Du dann nach PB übersetzt. Oder Du nimmst C++, dann gibt es auch
die Parameter by Reference.
Ich habe Visual-Studio Express 2012 installiert (eigentlich nur um einen Pacman-Klon in VB fertig zu schreiben, welchen ich während meiner bereits erwähnten Reha begann). Übrigens, falls es nicht rüberkam, mein Projekt ist eine Portierung von C(++) nach PureBasic; vielleicht bezogst Du Dich aber ja auch nur auf das Kompilieren Deines Beispiel-Codes.
auser hat geschrieben:In Beispiel 2 ist jedenfalls ein Fehler drin.
Oh! Danke, hab's korrigiert!
auser hat geschrieben:Stell dir das (by Reference) einfach als Vereinfachung für das Problem vor wenn du z.B. eine Funktion basteln willst die mehr als einen Wert zurückgeben soll. In PB oder C wirst du dazu wahrscheinlich Pointer bemühen. In C++ hättest du es einfacher.
(...)
Wär's nicht schön wenn dieses ganze gepeeke und poke verschwinden würde und du nicht ein @x brauchst um eine Adresse zu bemühen sondern einfach nur x schreiben kannst? Wäre PB ein bisschen eher wie C++ würde das gehen und dann irgendwie so aussehen (was freilich das aktuelle PB so nicht versteht):
Code: Alles auswählen
; Funzt ned ...
Procedure plus_eins(@a.i) ; PB versteht das nicht.
a = a + 1
EndProcedure
Define x.i = 0
plus_eins(x) ; geht net
Naja... geht doch fast so... Allerdings wäre ein richtiges ByRef schon schön! Besonders für Strings, da es dort ja keine Lösung gibt. Auch nicht mit Zeigern und/oder gepiekste und gestupse.
Code: Alles auswählen
; Funzt...
Procedure plus_eins(*a.Integer) ; PB versteht das.
*a\i + 1
EndProcedure
Define x.i = 0
plus_eins(@x) ; geht
auser hat geschrieben:An der Stelle will ich anmerken daß mir das Verhalten von C hier wesentlich besser gefällt. Da darf ich nämlich den Typ auf den der Pointer verweist setzen und lege fest wie er den Inhalt später lesen und schreiben darf. Also brauch ich dann nicht zig verschiedene PeekA, PeekB, PeekC, PeekI, PeekL, usw... und PokeB, PokeC, PokeI, PokeL usw... sondern einfach nur das "*".
Ich nutze lieber strukturierte Zeiger. Peeks und Pokes verwende ich eigentlich nur zum Debuggen oder wenn ich eine Demo-Code poste und davon ausgehe, dass das Gegenüber Anfänger ist und noch nicht mit Zeigern umgehen kann. Zeiger sind einfach schneller und übersichtlicher.
auser hat geschrieben:Und wenn ich irgendwann mal feststelle daß ich statt 1 Byte doch 4 Bytes brauche ändere ich halt den Typ im Header... wohingegen ich in PB dann überall im Program PeekB auf PeekL oder *a\b auf *a\l umschreiben muss.
Ich finde es zwar generell gut, dass man bei PureBasic (anders als bei C) standardmäßig im Code immer sofort erkennen kann, auf was für einen Typ der Zeiger verweißt, allerdings gibt's in PureBasic da einen ganz einfachen Trick, damit man genauso einfach wie in C den Typ nachträglich einfach im Header ändern kann! Hier mal mein Standard-Strukturen-Template:
Code: Alles auswählen
DeclareModule pbex_Structure
; anonyme Standardtypen
Structure AsciiN : n.a : EndStructure
Structure ByteN : n.b : EndStructure
Structure CharacterN : n.c : EndStructure
Structure DoubleN : n.d : EndStructure
Structure FloatN : n.f : EndStructure
Structure IntegerN : n.i : EndStructure
Structure LongN : n.l : EndStructure
Structure QuadN : n.q : EndStructure
Structure UnicodeN : n.u : EndStructure
Structure WordN : n.w : EndStructure
; offene Standard-Arraytypen
Structure AsciiArray : a.a[0] : EndStructure
Structure ByteArray : b.b[0] : EndStructure
Structure CharacterArray : c.c[0] : EndStructure
Structure DoubleArray : d.d[0] : EndStructure
Structure FloatArray : f.f[0] : EndStructure
Structure IntegerArray : i.i[0] : EndStructure
Structure LongArray : l.l[0] : EndStructure
Structure QuadArray : q.q[0] : EndStructure
Structure UnicodeArray : u.u[0] : EndStructure
Structure WordArray : w.w[0] : EndStructure
; anonyme offene Standard-Arraytypen
Structure AsciiArrayN : n.a[0] : EndStructure
Structure ByteArrayN : n.b[0] : EndStructure
Structure CharacterArrayN : n.c[0] : EndStructure
Structure DoubleArrayN : n.d[0] : EndStructure
Structure FloatArrayN : n.f[0] : EndStructure
Structure IntegerArrayN : n.i[0] : EndStructure
Structure LongArrayN : n.l[0] : EndStructure
Structure QuadArrayN : n.q[0] : EndStructure
Structure UnicodeArrayN : n.u[0] : EndStructure
Structure WordArrayN : n.w[0] : EndStructure
; String- und String-Arraytypen
Structure FixString : s.s{1} : EndStructure
Structure FixStringArray : s.s{1}[0] : EndStructure
Structure FixString2 : StructureUnion : s.s{1} : c.c : EndStructureUnion : EndStructure
Structure FixStringArray2 : StructureUnion : s.s{1}[0] : c.c[0] : EndStructureUnion : EndStructure
EndDeclareModule
Module pbex_Structure
; blind
EndModule
Bei Peek/Poke gestaltet sich das ganze natürlich etwas aufwendiger... Ich habe da mal ein wiederverwendbares Template geschrieben, mit dem das geht. Es bietet den Vorteil gegenüber Zeigern, dass die Größe des zu lesenden Typs dynamisch zur Laufzeit geändert werden kann. Da ich Prototypes verwende ist das ganze auch
relativ flott.
Ich habe mal geschwind den recht alten Code als Modul umgeschrieben (ich liebe die neuen Module!). Es ist also Vorsicht geboten! Es ist gut möglich, dass ich beim Umschreiben Fehler eingebaut habe. Ausgiebig getestet habe ich den Code noch nicht! Der Code enthält übrigens einige Redundanzen um ein fortlaufendes Schema zu garantieren (eigentlich war das ganze sowieso eher ein Machbarkeitsversuch).
Da der Code "ein ziemlicher Brocken" ist hier erstmal eine Kurzanleitung:
- Die ganzen "pbex_Memory_P..." Untermodule sind in "pbex_Memory" zusammengefasst, damit man einfach dort Funktionen auskommentieren kann und nur einen UseModule-Aufruf benötigt;
- Wo ich Makros nutze habe ich bei Zeigern das "*" durch ein "p" ersetzt (z.B. "pQuelle" statt "*Quelle");
- PeekValI() und PokeValI() sind für Integerwerte (alle in PB vorhandenen Typen);
- PeekValF() und PokeValF() für Gleitkommawerte (Float und Double);
- PeekVal() arbeitet statt mit einem Rückgabewert mit 2 Zeigern (1 Eingabe, 1 Ausgabe) und funktioniert mit allen Datentypen (Integer und Gleitkomma);
- Um den zu lesenden oder zu schreibenden Datentyp zu ändern ist jeder Peek- und Poke-Funktion eine Set...Type() Funktion zugeordnet. Zum ermitteln des aktuellen Datentypes gibt es ein Get-Pendant.
- Alternativ zu vorigem gibt es noch je eine Peek...Step() und Poke...Step() Funktion um die Schrittweite in Byte zu ermitteln (zum einfachen Zeiger inkrementieren).
- EDIT: Zu Beginn sind alle Prototypes auf eine Dummy-Prozedur gesetzt und Datentyp- wie Step-Prozeduren geben #False rück, damit ein IMA unwahrscheinlicher wird. Als erstes also den Datentyp festlegen! Sonst machen die Peek und Poke funktionen schlichweg überhaupt gar nichts!
Code: Alles auswählen
DeclareModule pbex_Memory_PeekVal
Prototype PeekVal(*Source, *Destination) : Global PeekVal.PeekVal
Declare.i PeekValStep(GetDestinationStep)
Declare.i GetPeekValType(GetDestinationType)
Declare.i SetPeekValType(SourceDataType, DestinationDataType)
EndDeclareModule
Module pbex_Memory_PeekVal
EnableExplicit
Macro PKV2(_sb_, _db_, _st_, _dt_)
Procedure PeekVal_#_sb_#_db_(*Source._st_, *Destination._dt_)
*Destination\_db_ = *Source\_sb_
EndProcedure
EndMacro
Macro PKV(_sb_, _st_)
PKV2(_sb_, A, _st_, Ascii)
PKV2(_sb_, B, _st_, Byte)
PKV2(_sb_, C, _st_, Character)
PKV2(_sb_, I, _st_, Integer)
PKV2(_sb_, L, _st_, Long)
PKV2(_sb_, Q, _st_, Quad)
PKV2(_sb_, U, _st_, Unicode)
PKV2(_sb_, W, _st_, Word)
EndMacro
Macro SPVT_Case2(_sb_, _db_, _st_, _dt_)
Case #PB_#_st_ | #PB_#_dt_ << 16
PeekValSourceStep = SizeOf(_st_)
PeekValDestinationStep = SizeOf(_dt_)
PeekVal = @PeekVal_#_sb_#_db_()
EndMacro
Macro SPVT_Case(_sb_, _st_)
SPVT_Case2(_sb_, A, _st_, Ascii)
SPVT_Case2(_sb_, B, _st_, Byte)
SPVT_Case2(_sb_, C, _st_, Character)
SPVT_Case2(_sb_, I, _st_, Integer)
SPVT_Case2(_sb_, L, _st_, Long)
SPVT_Case2(_sb_, Q, _st_, Quad)
SPVT_Case2(_sb_, U, _st_, Unicode)
SPVT_Case2(_sb_, W, _st_, Word)
EndMacro
PKV(A, Ascii)
PKV(B, Byte)
PKV(C, Character)
PKV(I, Integer)
PKV(L, Long)
PKV(Q, Quad)
PKV(U, Unicode)
PKV(W, Word)
Procedure PeekVal_DUMMY(*Source, *Destination) : EndProcedure
Global PeekValSourceStep, PeekValDestinationStep, PeekValSourceType, PeekValDestinationType
; Public
PeekVal = @PeekVal_DUMMY()
Procedure.i PeekValStep(GetDestinationStep)
If GetDestinationStep = #False
ProcedureReturn PeekValSourceStep
Else
ProcedureReturn PeekValDestinationStep
EndIf
EndProcedure
Procedure.i GetPeekValType(GetDestinationType)
If GetDestinationType = #False
ProcedureReturn PeekValSourceType
Else
ProcedureReturn PeekValDestinationType
EndIf
EndProcedure
Procedure.i SetPeekValType(SourceDataType, DestinationDataType)
If SourceDataType = #PB_Ignore : SourceDataType = PeekValSourceType : EndIf
If DestinationDataType = #PB_Ignore : DestinationDataType = PeekValDestinationType : EndIf
Select SourceDataType | DestinationDataType << 16
SPVT_Case(A, Ascii)
SPVT_Case(B, Byte)
SPVT_Case(C, Character)
SPVT_Case(I, Integer)
SPVT_Case(L, Long)
SPVT_Case(Q, Quad)
SPVT_Case(U, Unicode)
SPVT_Case(W, Word)
Default : ProcedureReturn #False
EndSelect
PeekValSourceType = SourceDataType
PeekValDestinationType = DestinationDataType
ProcedureReturn #True
EndProcedure
EndModule
DeclareModule pbex_Memory_PeekValI
Prototype.q PeekValI(*Memory) : Global PeekValI.PeekValI
Declare .i PeekValIStep()
Declare .i GetPeekValIType()
Declare .i SetPeekValIType(DataType)
EndDeclareModule
Module pbex_Memory_PeekValI
EnableExplicit
Procedure.q PeekValI_A(*Memory.Ascii) : ProcedureReturn *Memory\a : EndProcedure
Procedure.q PeekValI_B(*Memory.Byte) : ProcedureReturn *Memory\b : EndProcedure
Procedure.q PeekValI_C(*Memory.Character) : ProcedureReturn *Memory\c : EndProcedure
Procedure.q PeekValI_I(*Memory.Integer) : ProcedureReturn *Memory\i : EndProcedure
Procedure.q PeekValI_L(*Memory.Long) : ProcedureReturn *Memory\l : EndProcedure
Procedure.q PeekValI_Q(*Memory.Quad) : ProcedureReturn *Memory\q : EndProcedure
Procedure.q PeekValI_U(*Memory.Unicode) : ProcedureReturn *Memory\u : EndProcedure
Procedure.q PeekValI_W(*Memory.Word) : ProcedureReturn *Memory\w : EndProcedure
Procedure.q PeekValI_DUMMY(*Memory) : ProcedureReturn #False : EndProcedure
Global PeekValIStep, PeekValIType
; Public
PeekValI = @PeekValI_DUMMY()
Procedure.i PeekValIStep()
ProcedureReturn PeekValIStep
EndProcedure
Procedure.i GetPeekValIType()
ProcedureReturn PeekValIType
EndProcedure
Procedure.i SetPeekValIType(DataType)
Select DataType
Case #PB_Ascii : PeekValI = @PeekValI_A() : PeekValIStep = SizeOf(Ascii)
Case #PB_Byte : PeekValI = @PeekValI_B() : PeekValIStep = SizeOf(Byte)
Case #PB_Character : PeekValI = @PeekValI_C() : PeekValIStep = SizeOf(Character)
Case #PB_Integer : PeekValI = @PeekValI_I() : PeekValIStep = SizeOf(Integer)
Case #PB_Long : PeekValI = @PeekValI_L() : PeekValIStep = SizeOf(Long)
Case #PB_Quad : PeekValI = @PeekValI_Q() : PeekValIStep = SizeOf(Quad)
Case #PB_Unicode : PeekValI = @PeekValI_U() : PeekValIStep = SizeOf(Unicode)
Case #PB_Word : PeekValI = @PeekValI_W() : PeekValIStep = SizeOf(Word)
Default : ProcedureReturn #False
EndSelect
PeekValIType = DataType
ProcedureReturn #True
EndProcedure
EndModule
DeclareModule pbex_Memory_PokeValI
Prototype PokeValI(*Memory, Value) : Global PokeValI.PokeValI
Declare.i PokeValIStep()
Declare.i GetPokeValIType()
Declare.i SetPokeValIType(DataType)
EndDeclareModule
Module pbex_Memory_PokeValI
EnableExplicit
Procedure PokeValI_A(*Memory.Ascii , Value) : *Memory\a = Value : EndProcedure
Procedure PokeValI_B(*Memory.Byte , Value) : *Memory\b = Value : EndProcedure
Procedure PokeValI_C(*Memory.Character, Value) : *Memory\c = Value : EndProcedure
Procedure PokeValI_I(*Memory.Integer , Value) : *Memory\i = Value : EndProcedure
Procedure PokeValI_L(*Memory.Long , Value) : *Memory\l = Value : EndProcedure
Procedure PokeValI_Q(*Memory.Quad , Value) : *Memory\q = Value : EndProcedure
Procedure PokeValI_U(*Memory.Unicode , Value) : *Memory\u = Value : EndProcedure
Procedure PokeValI_W(*Memory.Word , Value) : *Memory\w = Value : EndProcedure
Procedure PokeValI_DUMMY(*Memory , Value) : : EndProcedure
Global PokeValIStep, PokeValIType
; Public
PokeValI = @PokeValI_DUMMY()
Procedure.i PokeValIStep()
ProcedureReturn PokeValIStep
EndProcedure
Procedure.i GetPokeValIType()
ProcedureReturn PokeValIType
EndProcedure
Procedure.i SetPokeValIType(DataType)
Select DataType
Case #PB_Ascii : PokeValI = @PokeValI_A() : PokeValIStep = SizeOf(Ascii)
Case #PB_Byte : PokeValI = @PokeValI_B() : PokeValIStep = SizeOf(Byte)
Case #PB_Character : PokeValI = @PokeValI_C() : PokeValIStep = SizeOf(Character)
Case #PB_Integer : PokeValI = @PokeValI_I() : PokeValIStep = SizeOf(Integer)
Case #PB_Long : PokeValI = @PokeValI_L() : PokeValIStep = SizeOf(Long)
Case #PB_Quad : PokeValI = @PokeValI_Q() : PokeValIStep = SizeOf(Quad)
Case #PB_Unicode : PokeValI = @PokeValI_U() : PokeValIStep = SizeOf(Unicode)
Case #PB_Word : PokeValI = @PokeValI_W() : PokeValIStep = SizeOf(Word)
Default : ProcedureReturn #False
EndSelect
PokeValIType = DataType
ProcedureReturn #True
EndProcedure
EndModule
DeclareModule pbex_Memory_PeekValF
Prototype.d PeekValF(*Memory) : Global PeekValF.PeekValF
Declare .i PeekValFStep()
Declare .i GetPeekValFType()
Declare .i SetPeekValFType(DataType)
EndDeclareModule
Module pbex_Memory_PeekValF
EnableExplicit
Procedure.d PeekValF_F(*Memory.Float) : ProcedureReturn *Memory\f : EndProcedure
Procedure.d PeekValF_D(*Memory.Double) : ProcedureReturn *Memory\d : EndProcedure
Procedure.d PeekValF_DUMMY(*Memory) : ProcedureReturn #False : EndProcedure
Global PeekValFStep, PeekValFType
; Public
PeekValF = @PeekValF_DUMMY()
Procedure.i PeekValFStep()
ProcedureReturn PeekValFStep
EndProcedure
Procedure.i GetPeekValFType()
ProcedureReturn PeekValFType
EndProcedure
Procedure.i SetPeekValFType(DataType)
Select DataType
Case #PB_Float : PeekValF = @PeekValF_F() : PeekValFStep = SizeOf(Float)
Case #PB_Double : PeekValF = @PeekValF_D() : PeekValFStep = SizeOf(Double)
Default : ProcedureReturn #False
EndSelect
PeekValFType = DataType
ProcedureReturn #True
EndProcedure
EndModule
DeclareModule pbex_Memory_PokeValF
Prototype PokeValF(*Memory, Value) : Global PokeValF.PokeValF
Declare.i PokeValFStep()
Declare.i GetPokeValFType()
Declare.i SetPokeValFType(DataType)
EndDeclareModule
Module pbex_Memory_PokeValF
EnableExplicit
Procedure PokeValF_F(*Memory.Float , Value.d) : *Memory\f = Value : EndProcedure
Procedure PokeValF_D(*Memory.Double, Value.d) : *Memory\d = Value : EndProcedure
Procedure PokeValF_DUMMY(*Memory , Value.d) : : EndProcedure
Global PokeValFStep, PokeValFType
; Public
PokeValF = @PokeValF_DUMMY()
Procedure.i PokeValFStep()
ProcedureReturn PokeValFStep
EndProcedure
Procedure.i GetPokeValFType()
ProcedureReturn PokeValFType
EndProcedure
Procedure.i SetPokeValFType(DataType)
Select DataType
Case #PB_Float : PokeValF = @PokeValF_F() : PokeValFStep = SizeOf(Float)
Case #PB_Double : PokeValF = @PokeValF_D() : PokeValFStep = SizeOf(Double)
Default : ProcedureReturn #False
EndSelect
PokeValFType = DataType
ProcedureReturn #True
EndProcedure
EndModule
DeclareModule pbex_Memory
; pbex_Memory_PeekVal
Macro PeekVal(pSource, pDestination) : pbex_Memory_PeekVal::PeekVal(*Source, *Destination) : EndMacro
Macro PeekValStep(GetDestinationStep) : pbex_Memory_PeekVal::PeekValStep(GetDestinationStep) : EndMacro
Macro GetPeekValType(GetDestinationType) : pbex_Memory_PeekVal::GetPeekValType(GetDestinationType) : EndMacro
Macro SetPeekValType(SourceDataType, DestinationDataType) : pbex_Memory_PeekVal::SetPeekValType(SourceDataType, DestinationDataType) : EndMacro
; pbex_Memory_PeekValI
Macro PeekValI(pMemory) : pbex_Memory_PeekValI::PeekValI(pMemory) : EndMacro
Macro PeekValIStep() : pbex_Memory_PeekValI::PeekValIStep() : EndMacro
Macro GetPeekValIType() : pbex_Memory_PeekValI::GetPeekValIType() : EndMacro
Macro SetPeekValIType(DataType) : pbex_Memory_PeekValI::SetPeekValIType(DataType) : EndMacro
; pbex_Memory_PokeValI
Macro PokeValI(pMemory, Value) : pbex_Memory_PokeValI::PokeValI(pMemory, Value) : EndMacro
Macro PokeValIStep() : pbex_Memory_PokeValI::PokeValIStep() : EndMacro
Macro GetPokeValIType() : pbex_Memory_PokeValI::GetPokeValIType() : EndMacro
Macro SetPokeValIType(DataType) : pbex_Memory_PokeValI::SetPokeValIType(DataType) : EndMacro
; pbex_Memory_PeekValF
Macro PeekValF(pMemory) : pbex_Memory_PeekValF::PeekValF(pMemory) : EndMacro
Macro PeekValFStep() : pbex_Memory_PeekValF::PeekValFStep() : EndMacro
Macro GetPeekValFType() : pbex_Memory_PeekValF::GetPeekValFType() : EndMacro
Macro SetPeekValFType(DataType) : pbex_Memory_PeekValF::SetPeekValFType(DataType) : EndMacro
; pbex_Memory_PokeValF
Macro PokeValF(pMemory, Value) : pbex_Memory_PokeValF::PokeValF(pMemory, Value) : EndMacro
Macro PokeValFStep() : pbex_Memory_PokeValF::PokeValFStep() : EndMacro
Macro GetPokeValFType() : pbex_Memory_PokeValF::GetPokeValFType() : EndMacro
Macro SetPokeValFType(DataType) : pbex_Memory_PokeValF::SetPokeValFType(DataType) : EndMacro
EndDeclareModule
Module pbex_Memory
; blind
EndModule
Falls es jemanden interessiert, so kann ich die Ankündigung machen, dass es vermutlich nicht mehr lange Dauert bis die sfxr-Portierung fertig ist (falls nicht etwas wichtigeres dazwischenkommt)! Die GUI läuft schon fehlerfrei, nur bei der Wave-Erstellung habe ich doch irgendwo einen bösen Fehler eingebaut... Sind sicher die Zeiger schuld!
