Autor Beitrag
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
  TSingleArray = array[0..0of 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Mi 06.01.10 12:15 
Hm. Was hällt dich davon ab, in der DLL eine Funktion wie folgt zu definieren?
ausblenden Delphi-Quelltext
1:
procedure foo(count:Integer;memory:Pointer)					


Aufruf dürfte klar sein.

Ansonsten wäre eher sinnvoll:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
TDynArray<T>=record
  RefCount:Cardinal;
  Count:Cardinal;
  Data: Array[0..Count-1of <T>; //<--Hier zeigt der Pointer der Array Variable hin.
end;


Also wäre die obere Procedure noch am Besten.
in Delphi definieren als:
ausblenden Delphi-Quelltext
1:
procedure foo(count:Integer;Memory:TBytes);stdcall;external...					


und in anderen Sprachen dann eben z.b. als:
ausblenden C#-Quelltext
1:
function foo(int Count,PByte Memory);					
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 06.01.10 15:51 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
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 user profile iconFlamefire 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.

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 06.01.10 16:53 
user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
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...

user profile iconBenBE hat folgendes geschrieben Zum zitierten Posting springen:
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."