Seite 1 von 1

Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 13:30
von ProgOldie
Hallo,
ich möchte von einem anderen Programm aus über eine DLL einen Speicherbereich reservieren und in ihm Daten ablegen, die dann von PB nach einem erneuten Aufruf aus dem Fremdprogramm weiterverarbeitet werden sollen.
Hintergrund: Die Daten sollen extrem schnell und unter Nutzung der Möglichkeiten von PB dargestellt werden können. Ein Beispiel wären astronomische Daten, die einmalig in den Speicherbereich geschrieben werden. Anschließend werden sie schnell und wiederholt ausgelesen, um dann visualisiert zu werden.
Zur Vereinfachung gehe ich davon aus, dass es sich um LongInt Daten handelt.

Leider fehlen mir reihenweise Kenntnisse über DLLs. Trotzdem ein kleiner Versuch:

Code: Alles auswählen

ProcedureDLL reserveMem(Mem.q)
  ; reserviert einen Speicherbereich der Größe Mem und reicht dessen Startadresse zurück
  *MemStart = AllocateMemory(Mem.q)
  If Not(*MemStart)
    MessageRequester("... gescheitert","Speichereinrichtung")
  EndIf
EndProcedure

ProcedureDLL saveMem(StoreNr.L,Wert.L)
  ;Schreibt den Wert mit der Nummer StoreNr in den Speicherbereich
  PokeL(*MemStart+(StoreNr-1)*4,Wert)
EndProcedure
Meine Probleme (u.a.):
a) ist die Idee grundsätzlich überhaupt realisierbar?
b) Wie reicht man aus der DLL die Startadresse des Speicherbereiches zurück?
c) Wie berücksichtigt man, dass es für 32-bit und 64-Bit funktioniert?

Dank schon 'mal vorab.

Re: Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 13:52
von NicTheQuick
Du definierst als Rückgabewert Integer und gibt's '*MemStart' einfach zurück. Der Integer passt sich automatisch an 32- oder 64-Bit-System an.

Code: Alles auswählen

ProcedureDLL.i reserveMem(Mem.q)
	; reserviert einen Speicherbereich der Größe Mem und reicht dessen Startadresse zurück
	
	Protected *MemStart = AllocateMemory(Mem.q)
	
	If Not (*MemStart)
		MessageRequester("... gescheitert", "Speichereinrichtung")
	EndIf
	
	ProcedureReturn *MemStart
EndProcedure
Damit du '*MemStart' auch in 'saveMem()' nutzen kannst, musst du '*MemStart' natürlich global machen.
Außerdem würde ich allgemein Integer (.i) nutzen und keine Longs (.l).

Re: Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 16:36
von ProgOldie
Hi Nick, very quick!
Könntest du noch 'mal einen Blick auf die folgende korrigierte Fassung werfen? Ich habe Sorge, dass ich mir bei einem Fehler mit AllocateMemory() das System zerschieße.

Code: Alles auswählen

Global *MemStart

ProcedureDLL.i reserveMem(Mem.q)
  ; reserviert einen(!) Speicherbereich der Größe Mem und reicht dessen Startadresse zurück 
  ; Wenn 0 zurückgereicht wird: Gescheitert
  If *MemStart    ;gibt einen ggf. zuvor reservierten Speicherbereich frei
    FreeMemory(*MemStart) 
  EndIf
  Protected *MemStart = AllocateMemory(Mem.q) 
  ProcedureReturn *MemStart
EndProcedure

ProcedureDLL saveMem(StoreNr.i,Wert.i)
  PokeI(*MemStart+(StoreNr-1)*4,Wert)
EndProcedure
O.K. so?

Re: Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 16:45
von _JON_
Mem.q lass da mal das ".q" weg macht keinen Sinn.
Wenn schon den schon ".i", aber integer ist Standard, muss also nicht geschrieben werden.

PokeI(*MemStart+(StoreNr-1)*4,Wert)

Ich weiß zwar nicht was Du hier machst aber PokeI schreibt unter x64 8 Bytes
vielleicht wäre es so besser:

PokeI(*MemStart+(StoreNr-1)*SizeOf(Integer),Wert)

Re: Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 16:48
von ts-soft
*MemStart ist global, also kein Protected vor dem allokieren, weil das wären dann 2 verschiedene Variablen, wobei eine
nur in der Procedur gültigkeit hätte!

Und was soll der quad bei mem? Anzahl Bytes in Integer!

Gruß
Thomas

//edit zu spät, aber das Global ist ja noch wichtig!

Re: Speicherbereich mit DLL ansprechen

Verfasst: 05.12.2014 17:31
von ProgOldie
Dank allen für die Korrekturen, die ich jetzt 'mal zusammengefasst habe. Zusätzlich habe ich noch eine Sicherung eingefügt, dass der Integerwert auch wirklich in den Bereich passt.

Code: Alles auswählen

Global *MemStart

ProcedureDLL.i reserveMem(Mem.i)
  ; reserviert einen(!) Speicherbereich der Größe Mem und reicht dessen Startadresse zurück 
  ; Wenn 0 zurückgereicht wird: Gescheitert
  If *MemStart    ;gibt einen ggf. zuvor reservierten Speicherbereich frei
    FreeMemory(*MemStart) 
  EndIf
  *MemStart = AllocateMemory(Mem) 
  ProcedureReturn *MemStart
EndProcedure

ProcedureDLL saveMem(StoreNr.i,Wert.i)
  ;Im Bereich stehen fortlaufend Integer-Werte;
  ;Der Integerwert mit der Nummer StoreNr erhält nun 'Wert'.
  If Int(MemorySize(*MemStart) / SizeOf(Integer)) > StoreNr  ; Dieser Integerwert passt hinein
    PokeI(*MemStart+(StoreNr-1)*SizeOf(Integer),Wert)
  EndIf
EndProcedure
Nun ist es hoffentlich richtig!