AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Wie Funktion einer DLL hundertfach hintereinander aufrufen??

Wie Funktion einer DLL hundertfach hintereinander aufrufen??

Ein Thema von christian.noeding · begonnen am 9. Okt 2005 · letzter Beitrag vom 10. Okt 2005
Antwort Antwort
Benutzerbild von christian.noeding
christian.noeding

Registriert seit: 26. Mai 2005
Ort: Knw.-Remsfeld
119 Beiträge
 
Delphi XE2 Professional
 
#1

Wie Funktion einer DLL hundertfach hintereinander aufrufen??

  Alt 9. Okt 2005, 19:11
Hallo,

Heute abend mal wieder eine DLL-Frage, da ich im Forum nichts passendes gefunden habe. Also: nachdem ich nun mit DLL-Programmieren und der dynamischen Einbindung derselben ein wenig Fuß gefasst habe, möchte ich eine bestimmte Funktion meines Programmes in eine DLL auslagern, damit man durch austauschen der DLL verschiedene Dinge mit den Parametern der Funktion anstellen kann, ohne das ganze Programm neu zu kompilieren (-> also eine Plugin-DLL)

Die DLL läuft soweit einwandfrei ohne ShareMem nur mit übergabe von PChars und mit Funktionsaufrufen über stdcall. Ich kann die DLL laden und auch die Funktionen und Forms laden, allerdings steigt mit jedem Funktionsaufruf die Speichermenge, die mein Programm verwendet und nach etlichen Aufrufen (>200) kratzt mir Delphi komplett mit Speicherfehlern ab (wahrscheinlich weil ich über meinen physikalischen RAM rausgehe)


Und das habe ich bisher programmiert:

Die DLL:

Delphi-Quellcode:
library pc_dimmer_com;

uses
  Forms,
  SysUtils,
  Classes,
  Windows,
  configfrm in 'configfrm.pas{Config},
  aboutfrm in 'aboutfrm.pas{About};

{$R *.res}

procedure DLLSenddata(address:integer; ftime:longint; level,st,fadetime_ms:integer);stdcall;
begin
  // hier der Funktionscode (der läuft ja, also lasse ich ihn hier weg)
end;

exports
  DLLSenddata;

begin
end.

und hier der Code, mit dem ich die DLL-Funktion aufrufe:

Delphi-Quellcode:
unit PCDimmer;

interface

uses
  {blablabla};

type
  TDLLSenddata = procedure(address:integer; ftime:longint; level,st,fadetime_ms:integer);stdcall;

  TMainForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm : TMainForm;
  OutputDLL: THandle;
  DLLSenddata:TDLLSenddata;

implementation

{$R *.DFM}

TMainform.button1click(Sender: TObject);
begin
  OutputDLL :=LoadLibrary(PChar('c:\meinplugin.dll'));
  @DLLSenddata := GetProcAddress(OutputDLL,'DLLSenddata');
end;

TMainform.scrollbar1change(Sender: TObject);
begin
  DLLSenddata(address,ftime,level,st,fadetime_ms);
end;

end.


Diesen Sourcecodeschnippsel habe ich jetzt eben aus meinem Hauptprogramm rausgeschrieben, ich hoffe ich habe nichts vergessen. Also ich lasse mir alle dll-Dateien in einem bestimmten Verzeichnis suchen und in einer Listbox anzeigen. Dann kann ich mit einem Button eine bestimmte Datei laden und die Funktion DLLSenddata mit der DLL-Funktion verbinden (Pointer setzen).

Wie gesagt, einige Male läuft die Funktion mit der Parameterübergabe, allerdings bereits nicht schnell. Ich hatte die DLL-Funktion DLLSenddata(...) vorher in der exe direkt drin und da flitzte die Funktion. Ausgelagert in der DLL schleicht die Funktion und frisst unmengen Speicher. Ich habe leider keine Ahnung, wo ich jetzt den Fehler suchen soll.


Vielleicht kann mir ja einer einen Tipp geben *g* Danke!


ciao, Christian
Christian Nöding
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 9. Okt 2005, 20:11
Hi,

also das deine Funktion so langsam ist, dürfte wohl damit zusammenhängen, dass du die jedes mal neu lädst. Das kostet natürlich Zeit, bedingt aber natürlich auch den Unterschied zwischen dynamischem und statischem Linken.
Wie auch immer, der Speicherbedarf ist halt eine andere Sache.

Lädst du jetzt eigentlich 200 mal die Dll und rufst dann die Funktion auf (also auch verschiedene dlls) oder lädst du einmal und kommt dann nach 200 Funktionsaufrufen das Problem?

Letzteres spricht natürlich für allozierten Speicher in der Funktion (und in ihren Funktionsaufrufen), der nicht freigegeben wird. Einerseits natürlich direkt in der Funktion, wenn du etwas erzeugst, musst du es explizit wieder freigeben, aber halt auch bei der Übergabe von Parametern musst du aufpassen. Wenn du die Parameter jedes mal neu erzeugst ohne die alten vorher freizugeben, z.B.:

Delphi-Quellcode:
function doFoo;
begin
  self.myBitmap := TBitmap.Create;
  // assign sth. to myBitmap
  ....
  myFunction(self.myBitmap)
end;
Dann hast du zwar immer genau die erwartete Bitmap an myFunction übergeben, aber jedes TBitmap.Create legt eine neue Bitmap an. Die Zuweisung ist dabei nur eine Zuweisung der Referenz self.myBitmap auf eine Bitmap, was mit der "Alten" passiert, auf die myBitmap nur gezeigt hat, ist Delphi egal. Die müsstest du mit einem self.myBitmap.Free natürlich freigeben.
Sorry wenn du das alles schon weißt und dich jetzt gelangweilt fühlst, aber kann man schnell mal drin haben.
Dann natürlich dynamische Arrays mit finalize(Array) ebenso freigeben.

Und zu guter letzt kommt natürlich noch eins in Frage, du benutzt loadLibrary, ähnlich wie gerade in doFoo erklärt, solltest du auch hier das Handle freigeben und deine Funktion um ein FreeLibrary erweitern.

Delphi-Quellcode:
TMainform.button1click(Sender: TObject);
begin
  if OutputDLL <> nil then
    begin
      if not FreeLibrary(OutputDLL) then
        begin
          // Fehler beim freigeben der DLL
          raise ...
        end; // if not FreeLibrary(OutputDLL)
    end; // if OutputDLL <> nil
  OutputDLL :=LoadLibrary(PChar('c:\meinplugin.dll'));
  @DLLSenddata := GetProcAddress(OutputDLL,'DLLSenddata');
end;
  Mit Zitat antworten Zitat
Benutzerbild von christian.noeding
christian.noeding

Registriert seit: 26. Mai 2005
Ort: Knw.-Remsfeld
119 Beiträge
 
Delphi XE2 Professional
 
#3

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 9. Okt 2005, 22:00
Hmm, erst mal danke für die Antwort...

ich lade die DLL (zur Laufzeit) nur einmal und rufe dann die Funktion nur sehr oft hintereinander auf. In der DLL-Funktion "DLLSenddata" wird (leider) überhaupt nichts erzeugt, was ich freigeben könnte. Ich rechne mit den Parametern nur ein bisschen rum, mache ein paar Bitverschiebungen und schiebe das ganze dann über den Com-Port mit einer Comport-Komponente raus.


Ich habe bisher auch nicht versucht, die DLL einmal statisch beim Programmstart zu laden... ich bin davon ausgegangen, dass die DLLs beim Laden zur Laufzeit sich nicht anders verhalten, wenn man sie nur einmal läd.


Also nochmal zusammen gefasst:
Delphi-Quellcode:
    OutputDLL := LoadLibrary(PChar('c:\plugin.dll'));
    @xDLLSenddata := GetProcAddress(OutputDLL, 'DLLSenddata');
und dann eben zum Beispiel über ne Scrollbar hintereinander (mit sich ändernden Parametern):

Delphi-Quellcode:
for i:=1 to 127 do
    xDLLSenddata(i,0,scrollbar1.position,1,0);

und mit jedem Ausführen der DLL-Funktion wird der Durchlauf immer langsamer :-/ das ist bei der Funktion im Exe-Code nicht passiert. Es muss also irgendwas im Speicher passieren. Eine nicht durchgeführte Freigabe, wie du sagst, klingt einleuchtend, nur was?


Hier mal der komplette Code der DLL:

Delphi-Quellcode:
library pc_dimmer_com;

uses
  Forms,
  SysUtils,
  Classes,
  Windows,
  configfrm in 'configfrm.pas{Config},
  aboutfrm in 'aboutfrm.pas{About};

{$R *.res}

function DLLGetName:PChar;stdcall;
begin
  Result := PChar('230V 128 Kanal PC_DIMMER');
end;

function DLLGetVersion:PChar;stdcall;
begin
  Result := PChar('v1.0');
end;

procedure DLLConfigure;stdcall;
var
  dllForm: TForm;
begin
  dllForm :=TConfig.Create(Application);
  try
    dllForm.ShowModal;
  finally
    dllForm.Release;
  end;
end;

procedure DLLAbout;stdcall;
var
  dllForm: TForm;
begin
  dllForm :=TAbout.Create(Application);
  try
    dllForm.ShowModal;
  finally
    dllForm.Release;
  end;
end;

procedure DLLSenddata(address:integer; ftime:longint; level,st,fadetime_ms:integer);stdcall;
var
  b:byte;
  t3,t2,t1:byte;
  rs232frame:array[0..5] of Byte;
begin
// Routine für COM1 bis COM16
// im Puffer alles auf 0 setzen
FillChar(rs232frame, SizeOf(rs232frame), 0);

  dec(address);
  b:=address;
  b:=b or $80; {erste byte high für Synchronisation}
  rs232frame[0]:=b; {erste Byte in Puffer schreiben}

//Steps in Byte 2 schreiben
  dec(st);
  b:=0;
  b:=b or st;
  rs232frame[1]:=b; {zweite Byte in Puffer schreiben}

// Fadezeiten in Byte 3..5 senden
  t1:=(lo(ftime) and $7F);
  ftime:=ftime shr 7;
  t2:=(lo(ftime) and $7F);
  ftime:=ftime shr 7;
  t3:=(lo(ftime) and $7F);
  rs232frame[2]:=t3; {dritte Byte in Puffer schreiben}
  rs232frame[3]:=t2; {vierte Byte in Puffer schreiben}
  rs232frame[4]:=t1; {fünfte Byte in Puffer schreiben}

// Endwert im Byte 6 senden
  b:=level and $7F;
  rs232frame[5]:=b; {sechste Byte in Puffer schreiben}
  Application.CreateForm(TConfig, Config);
  config.comport.SendData(@rs232frame,6);
end;

exports
  DLLGetVersion,
  DLLGetName,
  DLLConfigure,
  DLLAbout,
  DLLSenddata;

begin
end.


dieser Sourceschnippsel oben sollte direkt kompilierbar sein, wenn man die configfrm und aboutfrm rausnimmt... danke für jeden weiteren Tipp


schönen Abend noch,
Christian!


PS: keine Ahnung, obs was bringt, aber ich habe mal die fertig kompilierte DLL mit in den Anhang gehängt...
Angehängte Dateien
Dateityp: zip pc_dimmer_com_326.zip (261,4 KB, 9x aufgerufen)
Christian Nöding
  Mit Zitat antworten Zitat
Basilikum

Registriert seit: 9. Aug 2003
389 Beiträge
 
Delphi 7 Professional
 
#4

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 9. Okt 2005, 22:06
die Ursache für dein Memory-Leak dürfte wohl in dieser Zeile liegen:
Application.CreateForm(TConfig, Config);
  Mit Zitat antworten Zitat
Sepp

Registriert seit: 15. Sep 2004
Ort: Oberasbach
19 Beiträge
 
Delphi 6 Professional
 
#5

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 9. Okt 2005, 22:17
Hallo Christian

Basilikum schrieb
Zitat:
die Ursache für dein Memory-Leak dürfte wohl in dieser Zeile liegen:
Application.CreateForm(TConfig, Config);

Das Programm gibt die Objekte hier erst beim Beenden der kompletten Appl. frei.

Versuche es doch so

Delphi-Quellcode:
Config := TConfig.Create(Application);
Config.comport.SendData(@rs232frame,6);
FreeAndNil(Config);

Sepp
  Mit Zitat antworten Zitat
Benutzerbild von christian.noeding
christian.noeding

Registriert seit: 26. Mai 2005
Ort: Knw.-Remsfeld
119 Beiträge
 
Delphi XE2 Professional
 
#6

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 10. Okt 2005, 10:50
*Hand an den Kopf schlag*

Ja na klar, diese Zeile habe ich gestern wohl laufend übersehen. Diese Zeile habe ich nur hinzugefügt, da ich etwas basteln musste. Ich nutze wie gesagt eine Comport-Komponente. Wenn ich diese Komponente in einer DLL nutze und diese initialisiere, dann wird jeglicher Code nach der Initialisierungszeile nicht mehr ausgeführt. Daher habe ich die Komponente und alle zugehörigen Dinge in eine extra Unit gepackt und lasse die Form zu der Unit beim Senden jeweils neu createn. Das OnCreate-Ereignis initialisiert dann meine Komponente und sendet dann die Daten. Ich bin blöd: die Komponente wird anscheinend nicht wirklich freigegeben und bleibt dann zusammen mit der Form noch offen, was den Speicherbedarf natürlich enorm in die Höhe treibt.


Besten Dank für den Hinweis. Werde mich mal dransetzen. Vielleicht fällt mir ja auch noch eine elegantere Methode ein, um die Comport-Komponente besser zu nutzen.



ciao,
Christian
Christian Nöding
  Mit Zitat antworten Zitat
Sepp

Registriert seit: 15. Sep 2004
Ort: Oberasbach
19 Beiträge
 
Delphi 6 Professional
 
#7

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 10. Okt 2005, 10:55
Hallo Christian,

Zitat:
Ich bin blöd:
Ich würde sagen das kann einem schon mal passieren.

Wem das noch nicht selber passiert ist der lügt einfach.

Grüße und Ciao

Sepp
  Mit Zitat antworten Zitat
Benutzerbild von christian.noeding
christian.noeding

Registriert seit: 26. Mai 2005
Ort: Knw.-Remsfeld
119 Beiträge
 
Delphi XE2 Professional
 
#8

Re: Wie Funktion einer DLL hundertfach hintereinander aufruf

  Alt 10. Okt 2005, 15:42
Christian Nöding
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz