Autor |
Beitrag |
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 06.01.10 04:36
Aloha!
Ein kleines Plugininterface müsste eigentlich so etwas wie dynamische Arrays übertragen. Also einen Datenblock, der eine variable Anzahl von Werten übermittelt.
Das ganze soll natürlich auch in anderen Sprachen ansprechbar sein, also geht ein einfaches dynamisches Array nicht. Ich hab da schon etwas gegrübelt, aber viel weiter als ein Interface zu definieren, und dem Plugin eine Factory mit zu übergeben bin ich da nicht gekommen... das konnte ich bis jetzt schön umgehen, und würde es auch gern dabei belassen.
Momentan sieht die Struktur ungefähr so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| TSingleArray = array[0..0] of Single; PSingleArray = ^TSingleArray; TDynArray = record Count: integer; Data: PSingleArray; end; |
Das klappt momentan recht gut, indem das einfach "irgendwo" initialisiert wird, weil alle Verwendungen dann an einer Stelle vorbeikommen, wo ich aufräumen kann. Aber schön ist was anderes, und die Speicherlecks sind in späteren Stufen schon absehbar.
Andere kreative Ideen? Achja, einigermaßen schnell sollte zumindest das Erzeugen auch sein...
Danke schonmal,
Sebastian
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mi 06.01.10 12:15
Hm. Was hällt dich davon ab, in der DLL eine Funktion wie folgt zu definieren?
Delphi-Quelltext 1:
| procedure foo(count:Integer;memory:Pointer) |
Aufruf dürfte klar sein.
Ansonsten wäre eher sinnvoll:
Delphi-Quelltext 1: 2: 3: 4:
| TDynArray = record Count: integer; Data: Array of Single; end; |
Data ist schon ein Pointer auf den Inhalt des Arrays. Problem hier ist nur die Redundanz und Mehraufwand beim Verwalten von Count.
Der Aufbau eines dyn.Arrays in Delphi ist:
Delphi-Quelltext 1: 2: 3: 4: 5:
| TDynArray<T>=record RefCount:Cardinal; Count:Cardinal; Data: Array[0..Count-1] of <T>; end; |
Also wäre die obere Procedure noch am Besten.
in Delphi definieren als:
Delphi-Quelltext 1:
| procedure foo(count:Integer;Memory:TBytes);stdcall;external... |
und in anderen Sprachen dann eben z.b. als:
C#-Quelltext 1:
| function foo(int Count,PByte Memory); |
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 06.01.10 14:36
Abhängig davon, in welche Richtung die Daten ausgetauscht werden müssen, wäre auch die häufig in der WinAPI anzutreffende Variante mit der Übergabe eines Puffers (und ggf. Offset) auf den Datenbereich überlegenswert.
Alternativ bietet es sich, je nach Anzahl der Strukturen) auch an, einfach den Memory-Manager an die fremde Anwendung\das Plugin herauszureichen (Record TMemoryManager in System.pas IIRC) und so dem Plugin dynamisch zu erlauben, sich den nötigen Speicher zu holen.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Martok 
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 06.01.10 15:51
BenBE hat folgendes geschrieben : | Abhängig davon, in welche Richtung die Daten ausgetauscht werden müssen, wäre auch die häufig in der WinAPI anzutreffende Variante mit der Übergabe eines Puffers (und ggf. Offset) auf den Datenbereich überlegenswert. |
In jede Richtung, das ist ja das Problem. Mal muss das Plugin Daten loswerden, mal kriegt es welche geliefert. Ersteres ginge so wie Flamefire vorschlägt, aber das Problem ist grade die andere Richtung. Und die Tatsache, dass ich mir gerne das doppelt umkopieren sparen würde, sonst könnte ja einfach der Caller das Ding wieder freigeben.
BenBE hat folgendes geschrieben : | Alternativ bietet es sich, je nach Anzahl der Strukturen) auch an, einfach den Memory-Manager an die fremde Anwendung\das Plugin herauszureichen (Record TMemoryManager in System.pas IIRC) und so dem Plugin dynamisch zu erlauben, sich den nötigen Speicher zu holen. |
Funktioniert das vernünftig? Dann wäre das durchaus denkbar.
Dann kann ich aber gleich ein ordentlich referenzgezähltes IDynArray bauen.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 06.01.10 16:17
Die Variante mit dem Übergeben des Speichermanagers funktioniert sehr stabil und wird in vielen Plugin-Systemen von C-Programmen durchaus regelmäßig so praktiziert. Schau dir ggf. mal VirtualDub an; die machen das so und das Teil läuft SEHR stabil.
Gegenüber der Nutzung von Interfaces hat das zudem den Vorteil, dass man den Overhead, den die Verwaltung der Referenzen mit sich bringt vermeidet und das Plugin zudem intern bereits sich den Speicher aus dem Pool der Hauptanwendung holen kann und damit nicht nur Daten über das Interface problemlos verwaltet werden können, sondern auch zusätzliche Puffer, die intern im Plugin verwendet werden. Somit erspart man sich auch bei extrem verschachtelten Strukturen das Umkopieren, weil das Plugin die benötigten Strukturen ohne Umwege direkt im Speicher alloziieren kann.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Martok 
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mi 06.01.10 16:53
BenBE hat folgendes geschrieben : | Die Variante mit dem Übergeben des Speichermanagers funktioniert sehr stabil und wird in vielen Plugin-Systemen von C-Programmen durchaus regelmäßig so praktiziert. Schau dir ggf. mal VirtualDub an; die machen das so und das Teil läuft SEHR stabil. |
Ah stimmt, hab auch grade erstmal genau gelesen was du geschrieben hast  TMemoryManager sind ja nur die 3 Funktionspointer, nicht der IMemoryManager der das nochmal verpackt. Hab wohl zuviel mit Interfaces gearbeitet...
BenBE hat folgendes geschrieben : | Gegenüber der Nutzung von Interfaces hat das zudem den Vorteil, dass man den Overhead, den die Verwaltung der Referenzen mit sich bringt vermeidet |
Jap, das würde sich hier lohnen. RefCounting werd ich zwar eh machen müssen, aber das kann man dann genau da machen wo es gebraucht wird.
Das klingt erstmal gut, ich meld mich dann nochmal 
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
|