Autor Beitrag
Aya
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Di 24.10.06 22:57 
Hi,

ich habe ein mehr oder weniger verzwicktes problem.. zur erklärung muß ich ein wenig weiter ausholen :)
(Der Code an sich ist alles nur auf das minimalste beschränkt.. also nicht wundern wenn irgendwo ein Create oder ähnliches fehlt)

Ich schreibe ein programm welches eine Bild-sequenz darstellen soll.
Der user bekommt eine Zeitleiste angezeigt, und wenn er durch diese durchscrollt wird das entsprechende bild geladen + angezeigt.

Aus performance gründen Cache ich alle Bilder in einem Array of TBild (TBild ist ein Array mit Höhe * Breite * 4 of Byte) in einem extra Thread vor, was auch prima klappt.

Der Thread macht nichts anderes als die Bilder zu laden und in den Cache-Array zu schreiben.
Es kann nun aber auch vorkommen, das 2 oder mehr Cache-Threads gleichzeitig laufen, sprich die Sequenz an mehreren stellen gleichzeitig gecacht wird. Auch das funktioniert dank Synchronize/CritialSection wunderbar..

Und nun zu dem Problem:
Um x-beliebig viele Bildformate zu unterstützen habe ich die funktion für's laden in DLLs ausgelagert. Und nachdem eine DLL ja leider nur Integer's etc zurückgeben kann, und keine Bitmaps oder Dynamische Arrays, erstelle ich in der DLL eine Klasse welche vom Hauptprogramm verwendet werden kann:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
TDLLClass = class
  Image: TBild;
  procedure loadImage(Filename: PChar);
end;


die procedure loadImage lädt also das Bild und schreibt es in "Image". Der aufruf im Thread sieht dann etwa so aus:

ausblenden Delphi-Quelltext
1:
2:
DLLClass.loadImage('...');
Cache.Add(Frame, DLLClass.Image);


und das klappt ebenfalls wunderbar, allerdings nur solange es nur ein Thread ist...
Kommt jetzt ein zweiter Thread hinzu, überschneiden sich logischerweise die zugriffe auf die "Image"-Variable in der TDLLClass...

Und das ist die stelle wo ich ein wenig hänge grad... klar, ich könnte die Variable auch mit Synchronize/CriticalSections schützen, allerdings geht in dem Moment der sinn der Threads verloren, weil immer nur einer gleichzeitig auf die Image-Variable zugreifen könnte = nur ein Thread etwas cachen könnte..

Hat jemand eine Idee wie ich das problem lösen könnte?
Oder weiß jemand eine andere möglichkeit das Image was loadImage lädt aus der DLL in das Hauptprogramm zu bekommen?

Au'revoir,
Aya~

PS: Die DLL muß kompatibel zu VC++ bleiben!

_________________
Aya
I aim for my endless dreams and I know they will come true!
alias5000
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2145

WinXP Prof SP2, Ubuntu 9.04
C/C++(Code::Blocks, VS.NET),A51(Keil),Object Pascal(D2005PE, Turbo Delphi Explorer) C# (VS 2008 Express)
BeitragVerfasst: Di 24.10.06 23:17 
Ich bin mir nicht sicher, ob ichs vollständig verstanden habe, aber könnte es evtl. gehen, wenn du für jeden Thread eine eigene Instanz von TDLLCache erzeugst? Dann greifen die nicht mehr parallel auf eine Instanz zu...

Oder du machst aus loadimage ne Function und gibst als Rückgabewert das TBild zurück, dann würde die eine Variable entfallen. Aber ob das funktioniert, weiß ich nicht, da die Frage ist, was passiert, wenn zwei Threads parallel eine Funktion ausführen (da fehlt mir einfach die Erfahrung ;) )

Gruß alias5000

_________________
Programmers never die, they just GOSUB without RETURN
Aya Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Di 24.10.06 23:20 
Hi,

die sache mit mehreren Instanzen hatte ich auch überlegt, ist aber sehr sehr sehr ungünstig.. (wegen anderen sachen die noch passieren in der DLL Klasse).

Das mit der funktion und rückgabe.. das hatte ich irgendwie überhaupt nicht bedacht.. :shock: Rein von der logik her seh ich so spontan keinen grund warum das nicht klappen sollte, werd ich mal testen :)

Aya~

_________________
Aya
I aim for my endless dreams and I know they will come true!
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Di 24.10.06 23:25 
user profile iconAya hat folgendes geschrieben:
Um x-beliebig viele Bildformate zu unterstützen habe ich die funktion für's laden in DLLs ausgelagert. Und nachdem eine DLL ja leider nur Integer's etc zurückgeben kann, und keine Bitmaps oder Dynamische Arrays
Wie wäre es mit Pointern? :zwinker:

Zitat:
erstelle ich in der DLL eine Klasse welche vom Hauptprogramm verwendet werden kann:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
TDLLClass = class
  Image: TBild;
  procedure loadImage(Filename: PChar);
end;


die procedure loadImage lädt also das Bild und schreibt es in "Image". Der aufruf im Thread sieht dann etwa so aus:

ausblenden Delphi-Quelltext
1:
2:
DLLClass.loadImage('...');
Cache.Add(Frame, DLLClass.Image);
Und das geht ohne COM und ist immer noch mit VC++ kompatibel?

Zitat:
Hat jemand eine Idee wie ich das problem lösen könnte?
Oder weiß jemand eine andere möglichkeit das Image was loadImage lädt aus der DLL in das Hauptprogramm zu bekommen?
Gegenvorschlag zu deinem bisherigen Vorgehen:

Die DLL exportiert eine Funktion LoadImage(Filename: PChar; out Width: LongWord; out Height: LongWord; out Data: PLongWord), die das Bild inklusive Informationen an das Hauptporogramm zurückliefert. Nach Width und Height wird die Breite und Höhe gespeichert, in Data kommen die Bildinformationen in einem vorher festzulegenden Bildformat. Ich hätte hier an ein Zeilenverfahren gedacht, in dem Zeile für Zeile ein LongWord pro Pixel gespeichert wird, wenn du da irgendwie ein dreidimensionales Array draus gebastelt hast kann entweder das Hauptprogramm die Daten umwandeln oder die DLL legt sie gleich richtig im Speicher ab. Ein dynamisches Array wäre das dann zwar nicht mehr unbedingt, aber man kann sich ja mit einem type TPixelArray: array[0..0of TPixel; type PPixelArray: ^TPixelArray; behelfen, wenn man nur selten großartig an den Bildern rumschnippeln muss. Das Verfahren sollte ganz ohne Critical Sections thread-safe sein, sofern die einzelnen Funktionen für sich thread-safe sind (also die DLL intern nicht irgendwas böhses[tm] anstellt), vom gemeinsam verwalteten Bilder-Cache mal abgesehen, aber der ist ja so oder so nicht thread-safe.

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
Aya Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Di 24.10.06 23:42 
Hi,

das problem bei der sache wie du sie beschreibst ist, dsa ich in der DLL speicher für die Bilddaten reservieren müßte, was aber nicht geht (zumindest ist er bei mir immer abgeschmiert sobald ich das versucht habe) :(

Ich versuch jetzt erstmal das mit der function, vieleicht klappt das ja schon :)

Aya~

_________________
Aya
I aim for my endless dreams and I know they will come true!
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Di 24.10.06 23:52 
user profile iconAya hat folgendes geschrieben:
das problem bei der sache wie du sie beschreibst ist, dsa ich in der DLL speicher für die Bilddaten reservieren müßte, was aber nicht geht (zumindest ist er bei mir immer abgeschmiert sobald ich das versucht habe) :(
Wie hast du denn den Speicher allokiert? Mit einem GetMem() sollte es eigentlich keine Probleme geben, sonst würden schon ganz andere Dinge nicht funktionieren.

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
Aya Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1964
Erhaltene Danke: 15

MacOSX 10.6.7
Xcode / C++
BeitragVerfasst: Mi 25.10.06 00:03 
Hi,

ob ich GetMem ausprobiert hab weiß ich jetzt nicht genau... aber ich weiß, daß dashier nicht geht:

(Procedure/function einer DLL)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure loadImage(Filename: PChar; var Result: TBild)
begin
  [..]
  SetLength(Result, 6404803);
end;

function loadImage(Filename: PChar): TBild;
begin
  [..]
  SetLength(Result, 6404803);
end;


und das war auch der grudn warum ich das mit der function schon aus meinem kopf gestrichen hatte :(
Mit SetLength jedenfalls geht es nicht (ausser ich binde diese ShareMem Unit ein, aber das will ich nicht)

Aya~

_________________
Aya
I aim for my endless dreams and I know they will come true!
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Mi 25.10.06 00:15 
user profile iconAya hat folgendes geschrieben:
aber ich weiß, daß dashier nicht geht:[snip dynamic arrays
Ja nee, iss klar, dynamische Arrays sind genauso wie Strings, Objekte die wild von abstrakten Klassen abgeleitet sind und ähnliches Getier nicht über DLL-Grenzen hinweg ohne Weiteres benutzbar. Genauso wenig wie sie vom VC++ aus benutzbar sind. Daß dein obiges Vorgehen mit einem (Delphi-?)Objekt dies leisten soll, erstaunt mich schon ein wenig, aber wenn es geht, bist du Änderungen am ABI entweder des MSVC oder des DCC hilfslos ausgeliefert. Wenn plötzlich einer von beiden anfängt seine Wort-Grenzen anders auszurichten oder andere Änderungen am internen Layout von Objekten vornimmt, funktioniert das Ganze schon nicht mehr.
Wie gesagt, die einzig sichere MEthode sind Pointer auf Strukturen, die du selbst bestimmst, nicht auf welche, die der Compiler dir zur Verfügung stellt.

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert