Announcement

Collapse
No announcement yet.

MDI-Forms in DLL's ablegen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • MDI-Forms in DLL's ablegen

    Hi.

    Ich habe mit Hilfe des Abschnitts "BDE in einer DLL verwenden" aus Andreas Koschs "C/S Delphi"-Buchs versucht, DLL-Forms einzubinden. Geht auch soweit.

    Mein Probleme:
    - wir haben MDI-Formulare. Wie kann ich die einbinden und zwischen denen ganz normal wechseln?
    - Sinn der DLLs war die Reduktion des verwendeten Speichers. In dem o.g. Beispiel wird die DLL jedoch bei FormCreate geladen und bei FormDestroy freigegeben. Kann das Laden und Freigeben auch an anderen Stellen erfolgen? Wann wird der Speicher denn allokiert? Bei Laden der DLL oder beim Aufruf des Formulars?

    Frank Wolter

  • #2
    Hallo,

    ....Fragen über Fragen ;-)

    >Sinn der DLLs war die Reduktion des verwendeten Speichers.

    Dieses Ziel kann unabhängig von der DLL erreicht werden, oder genauer gesagt, jede Auslagerung in eine DLL <b>verschlechtert</b> zwangsläufig die Speicherbilanz zum Zeitpunkt des sichtbaren Formulars. Wesentlich ist, in welchen Zeitraum das Formular "lebt" und Ressourcen belegt. Wenn das Formular erst bei Bedarf erzeugt wird, und nach Gebrauch sofort wieder zerstört wird (Release oder caFree), ist keine DLL notwendig.

    >Kann das Laden und Freigeben auch an anderen Stellen erfolgen?

    Ja - was aber keine Vorteile bringt.

    >Wann wird der Speicher denn allokiert? Bei Laden der DLL oder beim Aufruf des Formulars?

    Windows lädt bei einem ausführbaren Modul (EXE oder DLL) immer nur den ausführbaren Codeteil in den Arbeitspeicher, aber die Ressourcen werden erst bei Bedarf nachgeladen. Delphi verpackt alle Formulare als speziellen Typ in die Ressourcen, so das zum Zeitpunkt des Ladens der DLL nur einige wenige kByte Arbeitsspeicher abgezweigt werden. Selbst wenn die DLL viel früher vom Programm "entladen" wird, bleibt die DLL dank dem Cache-Mechanismus von Win32 im Arbeitsspeicher! Win32 behält die DLL für den späteren Gebrauch solange, wie nicht der Arbeitsspeicher knapp wird. Erst dann, wenn über den Aufruf der <b>Schnittstellenprozedur</b> in der DLL das Formular erzeugt wird, macht sich das Formular im Speicher breit.

    Lange Rede kurzer Sinn: Es gibt durchaus Einsatzfälle, wo ein Formular in einer DLL Sinn macht. Das Einsparen von Ressourcen gehört jedoch nicht dazu

    Comment


    • #3
      Hmm, dann war ich wohl auf dem falschen Weg. Konkret ging es um ein Problem, daß ab einer bestimmten Größe des EXE-Files (ca. 6.5 MB) auf Win98-Rechnern die Fehlermeldung "Nicht genügend freier Arbeitsspeicher zum Starten des Programms kommt." Unter NT4 passiert nichts. Vermeiden konnte ich das nur, wenn ich einige Formulare wieder aus dem Projekt rausschmeiße. Die Formulare werden alle nur zur Laufzeit erzeugt, und ich kann mir darauf keinen Reim machen

      Comment


      • #4
        Hi

        Ich bin nicht ganz Andreas Meinung, DLL's verbrauchen zwar mehr Speicher (Festplatte/Memory) ABER, eine Anwendung wird wie ein großer Speicherblock geladen, DLL's können sich aber in verschiedenen Memoryblöcken befinden. Nun, Win95 kann nur Modul-orientiert Speicher in die Swap-Datei auslagern (wo sie ja keinen stört), ein 6.4 Mb großes Modul kann aber nicht ausgelagert werden das sonst das GANZE Modul ausgelagert werden müsste, wohlgemerkt unter Win95. Bei NT bin ich mir nicht ganz so sicher was die kleinste auslagerbare Einheit bildet, es scheint aber mödlich das dort auch gesplittete Speicherbereiche möglich sind. Wichtig ist, Windows muß igendwo eine Grenze ziehen was zu wem gehört, und dies bestimmt die kleinste Einheit, also ein Modul oder besser DLL.
        Ein nächstes Ding, Resourcen sind nicht gleich Resourcen, es gibt zum Beispiel normalen System-Speicher (DLL's, Module, Heap etc), dann gibt es GDI (User) Resourcen (Icon's, Bitmaps', Pinsel, etc) desweiternen Kernel Resourcen (Fensterhandles,Datei-handles, LockStructs, etc). Nun, diese speziellen Resourcen sind limitiert und werden "NICHT" in der Swap-Datei ausgelagert. Zum Beispiel stehen nur 2x 64KByte an Fensterhandles zur Verfügung. Nun, alle diese speziellen Resourcen sind den Modulen (EXE,DLL's) zugeordnet, wird eine DLL ausgelagert kann Windows auch diese auslagern/freigeben. Nun ein 6.5 Mb Modul kann nicht ausgelagert werden also auch nicht diese speziellen Resourcen. Eigentlich ist dies auch logisch.

        Nun, eine spezielle Form von DLL's wären die DPL's-Packages. Hier wären wir wieder bei einem Streitpunkt zwischen mir und Andreas (hi Andreas, ich glaube wir sollten mal drüber reden :-))). Ich vertrete die Meinung das Dir Packages helfen würden. Konkret, bei Deiner 6.5 Mb Anwendung nutzt Du sowieso fast alle VCL-Komponenten, also VCLXX.dpl,VCLDBxx.dpl etc. Nutzt Du nun diese Packages (so wie Delphi's IDE selber) verteilt sich der gemeinsam genutzte Code auf diese DPL's. Deine Module müssten so wie Deine Hauptanwendung mit Packages compiliert werden. Wir nutzen dieses Konzept, dies ergibt bei uns ca. 3 Mb für die Packages, 34KByte für die EXE, und ca. 50-100 Kb für ein Modul mit 1-2 Formularen. Nun, rechne mal nach !!
        Nur einen Fehler darfst Du nicht machen, alle DLL's ohne Packages compileren, dann benötigst Du für eine minimal-Anwendung ca. 500Kb für EXE und jeweils für jede DLL, logisch, da jedesmal Unit Classes,Forms,Controls,StdCtrls etc eingebunden werden müssen.
        EXE/DLL's mit Packages nutzen aber ein und den selben Unit-Code der Packages (also nur eine Unit Classes,Forms etc in z.B. VCL30.dpl).
        Werden die Packages geladen (sind ja DLL-Module) kann Windows auch alle Resourcen einer Instance zuordnen und somit sauber auslagern, und nach Bedarf laden. Ich weiß nicht genau warum Borland selber dieses Package-Konzept nutzt, nur um eben mal Benutzerdefinierte Packages zu ermöglichen kann nicht der einzigste Grund sein. Jedenfalls nutzten ALLE neueren Borland Tools (delphi IDE, BCB IDE, JBuilder IDE, selbst Tools wie TLIBIMP.EXE/DBExplorer/BRC32.exe etc) diese Methodik. Ich meine, setzt man diese Technick mit immer mehr Anwendungen fort wird sich der RESOURCEN-Verbrauch proportional verringern, mit normalen DLL's oder auch COM-Schnittstellen mit enthaltener VCL wird sich der Verbauch aber proportional vergrößern. Entscheiden ist hierbei der Knackpunkt, und der liegt nach meinen Erfahrungen bei ca. 4-5 Mb für die komplette Anwendung.

        Gruß Hage

        Comment


        • #5
          Hallo Hagen,

          Dein Einwand ist zwar prinzipiell richtig - aber das gemeinsame Teilen bezieht sich nur auf den statisch feststehenden Code-Bereich der DLLs, aber nicht auf die Datenbereiche. Ein "lebendes" Formular kann als Objekt nicht von verschiedenen Prozessen gemeinsam verwendet werden.

          Mit <i>Ressourcen</i> habe ich die RES-Daten gemeint, die der Linker an das Ende der EXE anhängt.

          Hagen hat auch völlig Recht, wenn er zur Beseitigung der Startfehlermeldung zum Einsatz von <b>Packages</b> rät. In diesem Fall ist das eine gute Alternative

          Comment


          • #6
            Hallo Hagen und Andreas.

            Danke für die Tips, es funktioniert jetzt mit Packages.

            Bis auf einen Umstand (D5 C/S): mit Runtime-Packages werden Komponenten in englisch übersetzt. Z.B. TBitBtn mit Kind=BKAbort, ModalResult=mrAbort und Caption=Abbrechen in der IDE zeigt "Abbrechen" an, beim Start des Programms allerdings "Abort". Stelle ich Kind=bkCustom, geht's. Dies betrifft auch die Aufrufe von "MessageDlg". Schalte ich die Runtime-Packages aus, klappt's wieder. Wir setzen die Sprach-Unterstützung nicht ein.

            Habt Ihr eine Erklärung dafür

            Comment


            • #7
              Hi Frank

              Du must für alle Delphi Packages die *.DE Files ( DLL's) mitliefern.
              Also für VCL50.bpl auch VCL50.de oder VCL50.nl wenn Du auch holländische Anwender hast. Diese DLL's sind die Sprachabhängigen Teile eines packages. Konkret, Deine Anwendung ist jetzt schon von den VCL-Komponenten her zwei-sprachig vorhanden. Schalte doch einfach in der Systemsteuerung auf Englisch um, und sofort wird Delphi englisch erscheinen. Diese Sprachabhängigen DLL's gibt es in fast allen Sprachen irgendwo im Netz zu downloaden. Der interne Ladeprozess eines Strings/Formulars etc. erkennt automatisch was für eine Sprache der Anwender nutzt, und lädt dann zu einem Modul die entsprechende Resourcen-DLL nach. Im Falle eines Deutschen ist das System auf DE, bzw. DEU eingestellt. Der Loader sucht also beim Laden von VCL50.BPL eine VCL50.DE Resourcen-DLL, findet er diese werden nun alle ResourceStrings und Formulare/Datenmodule nicht mehr aus VCL50.BPL sondern aus VCL50.DE geladen. Dies geschieht vollständig transparent. VCL50.BPL ist von hause aus english, benenne doch mal VCL50.DE im Windows\System\ Ordner um und starte dann Delphi neu.
              Also, setze die Property Kind=bkOk etc. NICHT um, Du büßt nur die schon vorhandene Sprachunabhängigkeit Deiner Anwendung ein, man weiß ja nie :-)), Achso, schau doch mal im Delphi-DEMO beim RichEdit Example rein, dort wird demonstriert wie man sogar zur Laufzeit einer Anwendung zwischen 5 Sprachen wechseln kann. Nocheins: diese Resourcen-DLL's enthalten absolut keinen Code, sind also reine, nachladbare sprachabhängige Resourcen-Files als DLL's verpackt.

              Hi Andreas

              Jain :-) Auf verschiedene Processe bezogen hast Du recht mit dem gemeinsamen teilen, innerhalb eines Processes greifen aber ALLE mit packages compilierten DLL's und die EXE auf ein und dieselben globalen Classen, Vars, Konstanten und funktionen eines Packages zu. Also, eine dynamisch geladene DLL die mit den selben Packages der EXE compiliert wurde greift auf die gleiche globale Application-Variable zu, wenn mit VCLxx.?pl compiliert wurde. Würde diese "Package"-DLL Application.Close aufrufen wird die Anwendung geschlossen.

              Borland's Trick: sie exportieren die Vars,Konstanten,Classtypen einfach als funktionen, aber eben so transparent und clever das man es gar nicht merkt. Du solltes mal mit dem MS-SDK Depency-Viewer die Exporte eines Packages genauer betrachten :-)
              Durchdenkt man das Packagekonzept (zumindestens ist es mir vor 2 Jahren so gegangen :-) wird man es immer mehr "bewundern" und die undendlichen Möglichkeiten entdecken. Ich gebe zu, auch mir ist es schwer gefallen es sofort vollständig zu begreifen, besonders weil sozusagen immer noch die eiserne Regel gilt "DLL's können NUR Funktionen exportieren". Im Grunde genommen gilt diese immer noch, nur das Vars,Konstanten usw. bei Borland im Hintergrund als funktionen bzw. funktionsaddressen exportiert/importiert werden.
              Ist eigentl. logisch, ich programmiere zwei DLL's die ein und dieselbe 3. DLL nutzen. Diese exportiert zwei Funktionen zum lesen und setzen einer privaten Variable. Benutzt Du nun einen cleveren Compiler der diese Zugriffsfunktionen der 3. DLL als variablen definition übersetzten kann, erscheint es Dir so als ob Du auf die globalen Variablen der 3. DLL aus den beiden anderen DLL's, zugreifst.

              Aber laß'es gut sein, meinem Kollegen habe ich 3 Tage erklären müssen was Packages bedeuten können :-)))))

              Gruß Hage

              Comment


              • #8
                Hallo Hagen,

                ich bin wohl eben doch nur zu faul, um Packages mit allen seinen Konsequenzen zu verwenden. Ohne Packages kann ich ein von Borland bereitgestelltes Sourcecode-Patch (ADO, IBX, DBTables etc.) ohne grossen Mehraufwand einbauen. Schaut man sich an, das für Delphi 5 immer noch kein offizielles UpdatePack (d.h. mit neuen VCL-Packages) vorliegt, haben Package-Nutzer einen echten Nachteil, denn die müssen warten, bis die offiziellen Packages der VCL fertig sind.

                P.S: Zwar kann man nach dem Einspielen der Sourcecode-Patches für die VCL eigene Packages neu compilieren und einbinden, aber diesen Mehraufwand tue ich mir wegen Faulheit nicht an ;-)

                Sogar Microsoft hat sich von der Idee verabschiedet, das sich DLLs gemeinsam ohne Kompatibilitätsprobleme nutzen lassen. Mit <i>Windows 98 SE</i> und <i>Windows 2000</i> wird aus diesem Grund das Konzept der <i>Side-by-Side-DLLs</i> eingeführt, d.h. jede Anwendung verwendet im ungünstigsten Fall einen eigenen, unabhängigen DLL-Satz

                Comment


                • #9
                  Hi Andreas

                  Wie immer steckt der Teufel im Detail.
                  Wenn Du die Patches von D3 bei Dir eingespielt hattest, um Fehler in der VCL zu beseitigen, musstes Du dann diese Packages NEU compilieren ?!?. NEIN, niemals. D.h. WENN Borland VCL-Patches auslieferte sind NUR interne Details geändert worden, oder NEUE Features hinzugefügt worden. In beiden Fällen ändert sich rein garnichts für Deine Module/EXE/Packages. Im ersten Fall, ändert sich an den Schnittstellen nichts, im zweiten Fall (neue Features) konntest Du zur Entwicklungszeit diese Features noch gar nicht kennen und somit auch nicht nutzen.
                  Du mußt bedenken, die Delphi IDE nutzt alle Packages selber, würde ein VCL-Patch bestehende Schnittstellen ändern müsstest Du auch Delphi selber patchen oder eine neue Version installieren. Das ist aber meiner Meinung nach noch NIE vorgekommen :-))

                  Ja,ja, ich sag's doch, um so länger man drüber nachdenkt um sehr mehr "bewundere" ich Packages. Heißt aber nicht das ich mir die Side- by-Side-DLL's sehr genau anschaue. Ich persönlich halte sie jetzt schon aus Sicherheitsaspekten für absolut unsicher. Stellt Dir vor Du erstellst solch eine DLL für den Login-Dialog !!

                  Gruß Hage

                  Comment


                  • #10
                    Hallo Hagen,

                    das Problem mit den VCL-Packages liegt ja darin, das Borland dafür gesorgt hat, das <b>niemand anderer als Borland</b> die "offizellen" VCL-Packages seiner Delphi-Version unter gleichem Namen neu compilieren kann. Damit wird verhindert, das chaotische Versionsprobleme auftreten. Und bei Delphi 5 gibt es jetzt ein dutzend ADO- und IBX-Patches, die eben dazu führen, das die Anwendungen keine Packages verwenden dürfen (denn die VCL-Packages von Delphi 5 sind ja noch nicht geändert worden, so das dort die Methoden immer noch fehlerhaft sind). Bei den Patches wird die Implementierung von bestimmten Methoden geändert, es werden keine neuen Sachen hinzugefügt. Somit werden diese Änderungen nur dann berücksichtigt, wenn die frisch compilierten DCU-Dateien im eigenen Projekt verwendet werden (d.h. der Linker muss diese geänderten Code-Blöcke in die eigene EXE einbinden).

                    Borland weist bei seinen Patches ausdrücklich darauf hin, das die Korrektur erst zur Laufzeit greift, aber <b>nicht</b> innerhalb der IDE. Die IDE arbeitet erst dann "fehlerfrei", wenn die offiziellen VCL-Packages über das angekündigte UpdatePack von Borland verteilt werden. Und genau das ist ja in der Vergangheit (Delphi 3 und Delphi 4) auch regelmässig passiert.

                    Die einzige Alternative für Anwendungen, die Packages nutzen, besteht darin, alle VCL-Komponenten nach dem Einarbeiten der Sourcecode-Patches in neuen, mit eigenen Namen versehenen Packages zusammenzufassen. Erst dann wird der frisch compilierte Bug-Fix auch von der eigenen Anwendung verwendet, wenn diese Packages verwendet.
                    &#10

                    Comment


                    • #11
                      Hi

                      Recht haste :-), sehe ich auch so, zeugt aber von schlampiger Programmierung der Borlandianer, ob die guten Vorsätze von Inprise (vor 1-2 Jahren) wieder vergessen wurden ?
                      Übrigens, die Methode eigene Packages zu erzeugen nutzen wir mit Drittanbietern, ändert meiner Meinung nach aber nichts am guten Konzept der Packages.

                      Gruß Hage

                      Comment

                      Working...
                      X