Puffer durch zwei Prozeduren durchreichen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Puffer durch zwei Prozeduren durchreichen

Beitrag von pcfreak1201 »

Hallo!

Ich hätte da gerne wieder ein Problem :-/
Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht, aber wie kann ich einen lokalen Puffer

Code: Alles auswählen

*sBuffer
so durchreichen, daß er erst in der 2. Prozedur gefüllt/allociert wird:
Procedure Proc1(*sBuffer)

Struct\*s2Buffer = *sBuffer
Proc2(@Struct)

EndProcedure

Procedure Proc2(*Struct)

*Struct\*s2Buffer = AllocateMemory (lBufSize)

EndProcedure
... und ich dann lokal auf das "Ergebnis" zugreifen kann?!
Ich sehe im Debugger die Adresse von *s2Buffer und entsprechenden Inhalt, doch lokal ist die Adresse dann wieder 0,
obwohl ich Proc1 mit (@*sBuffer) aufgerufen habe. :coderselixir:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von ts-soft »

Meinst Du sowas?

Code: Alles auswählen

Structure buffer
  *sBuffer
EndStructure

Procedure Proc2(*test.buffer)
  *test\sBuffer = AllocateMemory(100)
EndProcedure

Procedure Proc1()
  Protected test.buffer
  Proc2(@test)
  Debug MemorySize(test\sBuffer)
EndProcedure

Proc1()
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von pcfreak1201 »

Uh :shock: - gemein, eine Frage mit einer Gegenfrage zu beantworten 8)
Ich glaube aber, bei Deinem Beispiel fehlt eine Ebene - mal etwas konkreter:
Ich möchte diese Funktion kapseln und ín meinem Programm unterschiedlich aufrufen:
http://forums.purebasic.com/english/vie ... p?p=217254

Code: Alles auswählen

Procedure DownloadUrl(sUrl.s, *Buffer) 
  
Define tHTTP.T_PBL_HTTP_GET_FROM_WEB
  
tHTTP\sURL = sUrl
[...]
tHTTP\lDestination = #PBL_WRITE_TO_MEMORY
HTTPGetFromWeb (@tHTTP)
*Buffer = tHTTP\DestBuffer

EndProcedure 
... und rufe dazu im Hauptprogram

Code: Alles auswählen

Protected *buffer
  DownloadUrl("http://www.purebasic.de", @*buffer)
auf, und wollte dann den HTML-Code in *buffer mittels PeekS() auslesen.
Benutzeravatar
jojo1541
Beiträge: 431
Registriert: 15.09.2007 17:12
Wohnort: Irgendwo im Nirgendwo

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von jojo1541 »

Ich bin mir zwar nicht sicher, ob ich dein Problem verstehe, aber evtl. in etwa so?

Code: Alles auswählen

EnableExplicit

Global *TestBuf

Procedure SetBuf2(*Buffer)
  
  *Buffer = AllocateMemory(100)
  
  ProcedureReturn *Buffer
  
EndProcedure  
  
Procedure SetBuf1(*Buffer)
  
  Protected Pos.i
  
  Pos = SetBuf2(*Buffer)
  
  If Pos <> 0
    Debug "Erfolg. Pointer: " + Str(Pos)
    *TestBuf = Pos
  Else
    Debug "Erstellen des Speicherbereichs fehlgeschlagen"
  EndIf
    
  
EndProcedure

SetBuf1(*TestBuf)
Debug MemorySize(*TestBuf)
Ich verkaufe Rechtschreibfehler und jede menge GROßBUCHSTABEN. Alles unbegrenzt zu haben.
Derren
Beiträge: 558
Registriert: 23.07.2011 02:08

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von Derren »

*Irgendwas ist ein Pointer. Und der zeigt nunmal auf eine bestimmte Adresse im Speicher.
Du kannst nicht den gleichen Pointer in Prozeduren verwenden und erwarten dass du mit unterschiedlichen Speicherbereichen arbeiten kannst.

Entweder du benutzt CopyMemory() oder du machst dir eine Liste mit Pointern und übergibst die ItemID anstatt des Pointers an die Prozedur.
Signatur und so
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von pcfreak1201 »

Ahhh! Bäume! :o

Ok, notiere: die Adressen sind nicht dynamisch - davon war ich ausgegangen.
Jetzt wird es aber wieder unklarer:
Die ItemID kenne ich nur von den Gadgets - wenn wir das Gleiche meinen.
D.h. in meinem Fall, ich mache was?

Einen Integer-Wert anstatt einem Pointer übergeben? Oder geht das dann nur mit einer globalen Variablen?
Und was mache ich dann hieraus:

Code: Alles auswählen

*Buffer = tHTTP\DestBuffer
?
Das kann ich ja (u.U.) nicht ändern - also bleibt das auf alle Fälle ein Pointer?!
Derren
Beiträge: 558
Registriert: 23.07.2011 02:08

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von Derren »

So sollte es doch gehen?
Es geht ja nich um den Pointer in der Struktur, sondern um den Pointer, den du an die Proc2 übergibst.

Code: Alles auswählen

Procedure Proc1(*sBuffer)
	Protected var.Struct
	Struct\*s2Buffer = *sBuffer
	Proc2(var)
	
EndProcedure

Procedure Proc2(var)
	
	var\*s2Buffer = AllocateMemory (lBufSize)
	
EndProcedure
Evtl. muss var Shared sein, je nachdem was du vor hast
Signatur und so
Benutzeravatar
jojo1541
Beiträge: 431
Registriert: 15.09.2007 17:12
Wohnort: Irgendwo im Nirgendwo

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von jojo1541 »

Was heißt, die Speicheradressen sind nicht dynamisch... Der Pointer kann eben nur einen Wert gleichzeitig haben. (ist ja auch nur eine Variable). Du wirst also wohl oder übel für jeden Pointer eine Variable brauchen. Oder du machst es, wie Derren gesagt hat und nimmst eine Liste in der du die Pointer speicherst. Dann suchst du dir das richtige Element der Liste und benutzt den dort gespeicherten Pointer.

Edit: Ok, keine gute Idee, einen Beitrag zu schreiben und dann vom PC wegzugehen bevor man auf absenden drückt. Es passiert in der zwischenzeit so viel. /:->
Ich verkaufe Rechtschreibfehler und jede menge GROßBUCHSTABEN. Alles unbegrenzt zu haben.
Benutzeravatar
pcfreak1201
Beiträge: 38
Registriert: 17.12.2011 13:01
Computerausstattung: Linux Mint 17.3 (Rosa) x64 | PB 5.42LTS x64 (Linux+Win)
Wohnort: Arnsberg

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von pcfreak1201 »

Arg - macht mich nicht schwach! :freak: :?

Also ich habe ja oben mein Problem gepostet:

Code: Alles auswählen

Procedure DownloadUrl(sUrl.s, *Buffer) 
Dann sagt Derren
Du kannst nicht den gleichen Pointer in Prozeduren verwenden und erwarten dass du mit unterschiedlichen Speicherbereichen arbeiten kannst.
- OK, das erklärt, warum es nicht geht, da ja der Übergebene Pointer schon einen Wert hat, aber von der endgültigen Prozedur überschrieben werden müßte,
da hier ja erst die Zuweisung mit einem Speicherinhalt erfolgt, wenn die Datei heruntergeladen wurde.
Dann sagt Derren
So sollte es doch gehen?
Es geht ja nich um den Pointer in der Struktur, sondern um den Pointer, den du an die Proc2 übergibst.
Äh, es ist nix global, alles lokal. Das Ziel ist es, den Speicherinhalt aus dem Download in meine "Hauptprozedur" - nennen wir sie mal "Browser" - zu bekommen,
aber ich füge erst in

Code: Alles auswählen

DownloadUrl
einige Daten in die Struktur für

Code: Alles auswählen

HTTPGetFromWeb
ein.
Und da es sich wie in der Überschrift gesagt um ein Durchreichen handelt, sollte auch der Einwand von jojo
Der Pointer kann eben nur einen Wert gleichzeitig haben.
egal sein,
da es sich ja immer um den Wert des Pointers aus

Code: Alles auswählen

tHTTP\DestBuffer
handel soll, der ja in der Struktur mit

Code: Alles auswählen

*DestBuffer        ; if lDestination = #PBL_WRITE_TO_MEMORY will contain the address of the memory buffer allocated by the proc
  ; else it will contain 0
definiert ist.

... Ich habe übrigens als Workaround die UTF-8 nach ASCII-Wandlung in die Prozedur DownloadUrl gepackt. Damit funktioniert es zumindes, weil zwei unterschiedliche Puffer verwendet werden ...

Stefan :|
Derren
Beiträge: 558
Registriert: 23.07.2011 02:08

Re: Puffer durch zwei Prozeduren durchreichen

Beitrag von Derren »

Das Problem was du hast.
Du arbeitest nicht mit einer Variable, die eine Struktur hat, sondern du arbeitest mit dem Speicherbereich der Struktur.
Was für deine Anwendung völliger Blödsinn ist.
Du überschreibst quasi deine vorher definierte Struktur. Und jede Variable, die diese Struktur hat wird mit überschrieben.

Prozeduren können keine Strukturierten Variablen zurückgeben.
Deswegen hast du nur die Möglichkeit die strukturierte Variable, die in beiden Strukturen verwenden wird Shared zu definieren.

Vergiss mal Lokal. Du kannst ja nicht erwarten, dass du eine Lokale Variable in zwei Prozeduren verwenden kannst.

Das ist dein Problem.
Und dein Lösungsansatz sah wie folgt aus.
Anstatt eine Variable zu nutzen, schreibst du alles direkt in den Speicher.
Du hast aber nicht nur die Daten, die von Proc2 zurückgegeben werden in den Speicher geschrieben, sondern damit deine komplette Struktur überschrieben.
Das heißt der nächste Aufruf der Prozedur überschreibt wieder alles.

Also entweder du kopierst den Buffer vorher (CopyMemory()) oder du benutzt shared Variablen oder eben eine Liste.

Mach doch mal ein funktionsfähiges Beispiel.
Daran kann man es dir vielleicht besser erklären.
Signatur und so
Antworten