Entwickler-Ecke
Sonstiges (Delphi) - Dll mit Komponenten wie idHTTP
JayEff - Sa 23.04.05 18:21
Titel: Dll mit Komponenten wie idHTTP
Tach Leute. Nachdem meine andere frage bezüglich dlls nun geklärt ist, möchte ich versuchen, größere prozeduren in die dll auszulagern. Wie zum Beispiel diese:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41:
| Procedure TForm1.getChat; Var s: TStringlist; Messages: TIniFile; mes, abs, seens: String; Label nochmal; Begin nochmal: If length(Form3.Edit1.text) > 0 Then Begin s := TStringlist.Create; s.CommaText := IdHTTP1.Get('http://www.jayy.de/update/messages.txt'); s.savetofile('C:\tempMessages.ini'); s.text := ''; Messages := TIniFile.Create('C:\tempMessages.ini'); If Messages.ReadBool(Form3.Edit1.text, 'x', false) Then Begin mes := StringReplace(Messages.ReadString(Form3.Edit1.text, 'message', ''), '-', ' ', [rfReplaceAll]); abs := Messages.ReadString(Form3.Edit1.text, 'abs', '?'); Messages.EraseSection(Form3.Edit1.text); JaysMessage.zeigs('Nachricht erhalten!', abs + ' schrieb:' + #10#13 + mes); s.LoadFromFile('C:\tempMessages.ini'); Form3.IdFTP1.Put(TSTringStream.Create(s.text), 'messages.txt'); End; If Messages.ReadBool(' @all ', 'x', false) And (pos(Form3.Edit1.text, Messages.ReadString(' @all ', 'seens', '')) <= 0) Then Begin mes := StringReplace(Messages.ReadString(Form3.Edit1.text, 'message', ''), '-', ' ', [rfReplaceAll]); abs := Messages.ReadString(Form3.Edit1.text, 'abs', '?'); seens := Messages.ReadString(' @all ', 'seen', ''); Messages.WriteString(' @all ', 'seen', Form3.Edit1.text + ',' + seens); JaysMessage.zeigs('Message an alle!', abs + ' schrieb:' + #10#13 + mes); s.LoadFromFile('C:\tempMessages.ini'); Form3.IdFTP1.Put(TSTringStream.Create(s.text), 'messages.txt'); End; Messages.Free; If (pos(Form3.Edit1.text, s.text) > 0) Then Goto nochmal; deletefile('C:\tempMessages.ini'); End; End; |
Seht ihr das problem? ich will nich auf jeder Form eine idHTTP und eine idFTP haben. ich würde mir diese Units sparen: IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP! Weis nicht, wiviel das ausmacht. aber bestimmt genug... ^^
(Es geht hier übrigens ums vereinfachte und vom Volumen her kleinere Updaten)
Wie kann ich nun auf die Funktionen zugreifen, die runter- bzw hochladen können, gegebenenfalls auch mit einem Form mit diesen Komponenten in der dll? (Versuche endeten in einer Zugriffsverletzung)
Schange döhn schonmal, euer treuuuuuuuuues Mitglied Jay.. (PS: ja ich weis, meine u taste ist kapuuuuuuuuut ;) )
JayEff - Mo 14.08.06 21:09
| Richtlinien hat folgendes geschrieben: |
4.6 Schiebeposting
Schiebeposting (ein Posting um sein eigenes Topic für unsere Leser wieder als ungelesen zu markieren) sind nach 24 Stunden erlaubt. Es gibt keine Begrenzung von Schiebepostings, sofern ihr Abstand 24 Stunden beträgt. |
:!:
Ich mag den Paragraph... However: Das Problem besteht weiter. Kann ich CLS-Komponenten in einer DLL verwenden? Hab schon vieles versucht, wie x:TidHTTP und x:=TidHTTP.Create(lool.foo.? nil!); Aber meistens endete es in Acces Violations.
JayEff - Di 15.08.06 22:50
Hmm.. scheint nicht, als ob es eine Lösung für dieses Problem gäbe. Vermutlich muss man sich diese Proceduren selbst schreiben oder so...
JayEff - Di 15.08.06 23:02
Narses hat mir eine nicht für Skriptkiddies geeignete PN geschrieben ;) Ich hab mal eine kleinigkeit rausgenommen ... :
Er hat gemeint, dass DLLs über keinen MessageLoop verfügen.
Aaaha. verstehe. Ich kann die Komponente desshalb nicht benutzen, weil z.B. Ereignisse für sie nicht verarbeitet werden könnten, verstehe ich das richtig?
Könnte ich nicht einfach eine Form in die DLL klatschen und diese als Parent für die TidFTP nehmen? Dann müsste ich immer die Form auf invisible stellen und schon könnte ich die Komponente ohne Einschränkungen benutzen, oder?
Dann müsste mir einer kurz erklären, wie ich eine Form in die DLL packe :oops:
PS: Updater-Anwendung hab ich ja, aber das veringert doch die größe der Anwendung nicht, oder? :shock: Also eine Anwendung, die das Update runterlädt und ausführt.
Narses - Mi 16.08.06 00:06
Moin!
Es geht nicht um das
TForm, sondern um das
TApplication-Objekt. ;)
Weiterhin: Ahrg! Das verbotene Wort
label und die
goto-Sünde... ;)
JayEff hat folgendes geschrieben: |
| ich will nich auf jeder Form eine idHTTP und eine idFTP haben. ich würde mir diese Units sparen:... |
Der Linker bindet doch nicht mehrfach die Units in die Anwendung ein, so schlau ist der schon. ;) Im Gegenteil, wenn du den DLL-Ansatz weiter verfolgst, dann handelst du dir tatsächlich diese Units in jeder DLL ein.
Fazit: Diese Teile in eine DLL zu packen ist eher nicht so schlau. Deshalb: entweder auf Packages ausweichen oder in der Hauptapplikation lassen und parametrisiert verwenden.
cu
Narses
JayEff - Mi 16.08.06 00:11
Hm..Den Teil hab ich nich kapiert:
"Der Linker bindet doch nicht mehrfach die Units in die Anwendung ein, so schlau ist der schon. Im Gegenteil, wenn du den DLL-Ansatz weiter verfolgst, dann handelst du dir tatsächlich diese Units in jeder DLL ein."
und was du mit Package meinst (.dpk? :shock: ) bzw mit "parametrisiert verwenden" auch nicht ... ^^
das lable und goto .. nun ja.. recht hast du ^^ Ich benutz es nur, wenn ich keine andere Möglichkeit finde. Warum is das eigentlich so verschrien um etwas OT zu betreiben ... ?
Narses - Mi 16.08.06 00:24
Moin!
JayEff hat folgendes geschrieben: |
Hm..Den Teil hab ich nich kapiert:
"Der Linker bindet doch nicht mehrfach die Units in die Anwendung ein, so schlau ist der schon. |
Wenn du in mehreren Formularen deiner Anwendung die gleichen Units einbindest, dann wird trotzdem in der Anwendung nur einmal der Code der Unit enthalten sein.
JayEff hat folgendes geschrieben: |
| Im Gegenteil, wenn du den DLL-Ansatz weiter verfolgst, dann handelst du dir tatsächlich diese Units in jeder DLL ein." |
Wenn du dagegen ein unabhängiges Modul machen willst, dann muss der Linker den Code auch in jedem Modul unterbringen.
JayEff hat folgendes geschrieben: |
| und was du mit Package meinst (.dpk? :shock: ) |
Ich meine .bpl-Dateien, einfach mal in der DOH nachlesen.
JayEff hat folgendes geschrieben: |
| bzw mit "parametrisiert verwenden" auch nicht ... |
Gestalte die Nutzung der Indies in der Applikation so, dass eine DLL auch darauf zugreifen kann, wenn du denn schon unbedingt DLLs verwenden willst. Fazit: du machst einen Indy-Wrapper in deine Anwendung und auf den greifst du dann zu. So bleibt die Indy-Kompo in der Haupt-App und wird von den andern Teilen genutzt. Da die Indies wohl nicht sehr häufig ein Update brauchen, ist dein Code-Größen-Problem doch damit behoben. Oder hab ich dich jetzt falsch verstanden? :? ;)
JayEff hat folgendes geschrieben: |
| das lable und goto .. nun ja.. recht hast du ^^ Ich benutz es nur, wenn ich keine andere Möglichkeit finde. Warum is das eigentlich so verschrien um etwas OT zu betreiben ... ? |
Man kann beweisen, dass label/goto "unnötig" sind, bzw. sich immer durch bessere Kontrollstrukturen ersetzen lassen. Soviel zu "keine andere Möglichkeit". ;) Verschrien ist goto deshalb, weil es sogenannten "Spaghetti-Code" erzeugt und dabei gar nicht notwendig ist. :D
cu
Narses
JayEff - Mi 16.08.06 00:36
Die DLL wollte ich benutzen, damit, falls ein Update herunter geladen muss, die größe des Updates minimal bleibt. Also wollte ich die Grafiken und das Hauptprogramm so gestalten, dass es nur einmal heruntergeladen werden muss, während die DLL geupdatet werden kann, bzw umgekehrt. Auf diese Art müsste man nur die Hälfte des Programmes beim Update herunterladen, das war der Grund warum ich diese funktion in die DLL auslagern wollte. Also würden die idFTP (usw. ) units nur einmal, nämlich in der DLL auftauchen. Klar, dass der Code der Unit nur einmal eingebunden wird, auch wenn ich 100 mal in verschiedenen units "uses aUnit" eintrage.
Die DLL habe ich ja nur desshalb geschrieben, weil ich die Größe der Anwendung veringern wollte. Gut, DLL+Anwendung zusammen sind natürlich größer, als wenn ich die Funktionen alle in der Hauptanwendung gelassen hätte.
Was ich sagen will: Ich KÖNNTE auf die DLL verzichten - die DLL MUSS nicht unbedingt auf eine idFTP Komponente zugreifen, WENN, dann macht es nur Sinn, die ganze Prozedur samt Komponente auszulagern (denke ich ... ).
Was ist "Spagetti-Code"? (Meinst du den ASM code oder was genau?) Aah ich weis schon.. ich google mal ^^
Klar könnte man irgentwie drauf verzichten, aber manchmal fällt mir nicht ein, wie ^^ In meinem Beispiel per Rekursion, versteh schon, das ist natürlich sehr viel einfacher... Werds bei Gelegenheit ändern.
Martok - Mi 16.08.06 03:53
Ich habs dir mal ent-Goto-t:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| Procedure TForm1.getChat; Var s: TStringlist; Messages: TIniFile; mes, abs, seens: String; Begin If length(Form3.Edit1.text) > 0 Then Begin repeat s := TStringlist.Create; s.CommaText := IdHTTP1.Get('http://www.jayy.de/update/messages.txt'); s.savetofile('C:\tempMessages.ini'); s.text := ''; Messages := TIniFile.Create('C:\tempMessages.ini'); If Messages.ReadBool(Form3.Edit1.text, 'x', false) Then Begin mes := StringReplace(Messages.ReadString(Form3.Edit1.text, 'message', ''), '-', ' ', [rfReplaceAll]); abs := Messages.ReadString(Form3.Edit1.text, 'abs', '?'); Messages.EraseSection(Form3.Edit1.text); JaysMessage.zeigs('Nachricht erhalten!', abs + ' schrieb:' + #10#13 + mes); s.LoadFromFile('C:\tempMessages.ini'); Form3.IdFTP1.Put(TSTringStream.Create(s.text), 'messages.txt'); End; If Messages.ReadBool(' @all ', 'x', false) And (pos(Form3.Edit1.text, Messages.ReadString(' @all ', 'seens', '')) <= 0) Then Begin mes := StringReplace(Messages.ReadString(Form3.Edit1.text, 'message', ''), '-', ' ', [rfReplaceAll]); abs := Messages.ReadString(Form3.Edit1.text, 'abs', '?'); seens := Messages.ReadString(' @all ', 'seen', ''); Messages.WriteString(' @all ', 'seen', Form3.Edit1.text + ',' + seens); JaysMessage.zeigs('Message an alle!', abs + ' schrieb:' + #10#13 + mes); s.LoadFromFile('C:\tempMessages.ini'); Form3.IdFTP1.Put(TSTringStream.Create(s.text), 'messages.txt'); End; Messages.Free; until pos(Form3.Edit1.text, s.text) = 0; deletefile('C:\tempMessages.ini'); End; End; |
Obwohl ich gestehen muss, grade bei Case-Statements benutze ich goto doch manchmal, mir fehlt einfach diese fallthrough-Funktionalität aus C, also wenn kein break da steht wird die Abfrage auch nicht verlassen.
Narses - Mi 16.08.06 08:08
Moin!
Ich sehe gerade, dass meine Hinweise bzgl. MessageLoop auf deinen Fall gar nicht zutreffen... :? ;) (war wohl doch schon etwas später gestern... ;))
Fragt sich also, wie deine Funktion aus der DLL deklariert ist, sprich, wie sieht die Parameterübergabe aus?
cu
Narses
JayEff - Mi 16.08.06 14:58
Das würde dann wohl in etwa so aussehn:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| uses FastShareMem, Windows, SysUtils, Classes, shellapi, Registry, IdFTP, idHTTP;
Function xx: String Stdcall; Var IdFTP: TidFTP; idHTTP: TidHTTP; Begin IdFTP := TidFTP.Create(Nil); idHTTP := TidHTTP.Create(Nil); IdFTP.Host := 'http://'; IdFTP.Username := ''; IdFTP.Password := ''; result := idHTTP.Get('www.jayy.de/index.php'); IdFTP.Free; idHTTP.Free; End;
Exports xx;
End. |
Bei nem Aufruf von showmessage(xx); kommt:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project2.exe ist eine Exception der Klasse EIdHTTPProtocolException aufgetreten. Meldung: 'HTTP/1.0 501 Not Implemented'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------
Also das wär nen Test.
Narses - Mi 16.08.06 15:08
Moin!
Und wenn du die FTP+HTTP-Kompo weiter in der Hauptapplikation lässt und nur eine Referenz darauf übergibst? (also die Kompos nicht in der DLL erzeugst, weil genau das ist das Problem) Würde genau den von mir angesprochenen Code-Spareffekt erzielen. ;)
cu
Narses
JayEff - Mi 16.08.06 15:15
Hm.. Ich wüsste nicht, wie ich von der DLL aus auf eine Komponente in der Hauptapp zugreifen könnte... Du hast etwas von einem Wrapper gesagt ... das sollte ich mir vielleicht mal anschauen, wa? Aber dann spare ich mir in der Hauptapp nicht wirklich die Units.. Hmm. Ich könnte ja Umdenken, und die Prozeduren in die DLL packen, die wahrscheinlicher geupdatet werden müssen. Hm ja.. dann müsste ich natürlich rausfinden, wie ich auf die Indys zugreifen kann.
Narses - Mi 16.08.06 16:38
Moin!
JayEff hat folgendes geschrieben: |
| Hm.. Ich wüsste nicht, wie ich von der DLL aus auf eine Komponente in der Hauptapp zugreifen könnte... |
Wie wäre es so: ;)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| uses FastShareMem, Windows, SysUtils, Classes, shellapi, Registry, IdFTP, idHTTP;
Function xx(IdHTTP: TIdHTTP): String Stdcall; Begin result := idHTTP.Get('www.jayy.de/index.php'); End;
Exports xx;
End. |
Die Kompo selbst in der HauptApp erzeugen und freigeben, dann nur die Referenz darauf übergeben. Fertig.
cu
Narses
Narses - Mi 16.08.06 22:53
Moin!
Es hat mir einfach keine Ruhe gelassen und ich muss gestehen - ich hatte es auch wohl nicht mehr so ganz richtig in Erinnerung... (hab da was mit den alten Socket-Kompos verwechselt... :oops:) ;)
@
JayEff: Ich weiß nicht so ganz genau, wo dein Problem im Code liegt, aber die Indies sind durchaus in der Lage, sich dynamisch in einer DLL instanziieren zu lassen (zumindest IdHTTP und IdFTP von Indy9; vermutlich, da blocking socket calls gemacht werden; schätze, bei asynchronen WSA-Ereignissen wird´s trotzdem noch Probleme geben). Hier ist mein Testprojekt, funktioniert.
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!