AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

DLL Problem mit XE7

Ein Thema von helste · begonnen am 8. Apr 2015 · letzter Beitrag vom 9. Apr 2015
Antwort Antwort
Seite 1 von 3  1 23      
helste

Registriert seit: 16. Jul 2009
72 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

DLL Problem mit XE7

  Alt 8. Apr 2015, 15:22
Hallo,

ich stehe gerade vor einem Problem, wo ich nicht mehr weiter weiß.
Ich habe einige Programmteile in einer DLL. Der Hintergrund ist der, dass ich neue Programmteile in Delphi XE (derzeit XE7) programmiere, aber das Hauptprogramm immer noch mit Delphi 2007 warten muss. Geht einfach nicht, das alles mit vertretbarem Aufwand umzustellen.
Das Problem ist nun, dass Routinen in meiner DLL, die immer funktioniert haben, plötzlich nicht mehr laufen.
Wenn ich die DLL mit Delphi XE5 kompiliere, funktioniert alles einwandfrei. Kompiliere ich sie mit XE7, gibt es Probleme.
Ein Problem ist, dass einige Proceduren zwar machen was sie sollen, dann beim Beenden des Hauptprogrammes aber ein Runtimeerror 207 generiert wird oder das Hauptprogramm einfach nicht mehr freigegeben wird. Das läuft dann mit ca. 25% Prozessorleistung weiter (im Taskmanager sichtbar).
Ich habe nun ein kleines Testprogramm geschrieben, welches eine der problematischen Proceduren aufruft. Da passiert es nun schon, dass das Programm kommentarlos beendet wird, sobald ich die Procedure aus der DLL lade. Wird die DLL mit Delphi XE5 kompiliert, funktioniert alles. Kompiliere ich mit XE7 gibt es das Problem. Das besteht übrigens auch, wenn das rufende Programm mit XE7 kompiliert wird. Liegt also nicht an Delphi 2007.
Ich weiß nun echt nicht mehr weiter. Woran kann das unterschiedliche Verhalten beim Kompilieren bzw. Linken der DLL zwischen XE5 und XE7 liegen? Habe ich da im XE7 irgendwas nicht richtig eingestellt?

Ich hoffe es kann mir wer helfen. Hänge nun schon seit 3 Tagen mit diesem Problem rum.

LG
Helmut
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#2

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 15:30
Die Frage ist voallem erstmal was ausgelagert wurde, bzw. wie die Prozeduren/Interfaces asussehen.

Was für Typen haben denn die Parameter und welche Aufrufkonvention wird benutzt?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
helste

Registriert seit: 16. Jul 2009
72 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 15:50
Das ist etwas schwierig auf einen Nenner zu bringen.
Ich habe ganze Eingabemasken inklusive Datenbankzugriff, die problemlos funktionieren. Dann gibt es wieder welche, die das Problem verursachen.
Bei einer Maske musste ich z.B. TFileSaveDialog durch TSaveDialog ersetzen, damit sie funktioniert. Die selbe DLL mit TFileSaveDialog mit Delphi XE5 kompiliert macht kein Problem.

In der DLL kann das z.B. so aussehen:

Code:
procedure edit_test; stdcall;

begin
.....
end;
im rufenden Programm kommt dann z.B. folgendes:
Code:
var
  edit_test : procedure; stdcall;
  testdll : HMODULE;


procedure TForm1.Button1Click(Sender: TObject); // DLL laden

begin
testdll := LoadLibrary('testdll.dll');
if testdll <> 0 then
   begin
   @edit_test := GetProcAddress(testdll, 'edit_test');
   end;
end;

procedure TForm1.Button2Click(Sender: TObject); // Routine aufrufen

begin
edit_test;
end;

procedure TForm1.Button3Click(Sender: TObject); // DLL freigeben
begin
FreeLibrary(LHnd);
edit_test := nil;
end;

Ich habe das zum Testen bewusst auf 3 Schalter gelegt. Beim Drücken von Button1 wird das Programm jedoch schon kommentarlos beendet.


Ich werde versuchen ein komplettes Programm samt kompletter DLL zu erstellen, welches möglichst einfach gehalten ist, aber das Problem bringt. Ich hoffe das gelingt.

Ich weiß, so wird es schwierig. Warum kompiliert XE5 die DLL so, dass sie funktioniert und XE7 macht Mist? Das ist mal die Hauptfrage, die mich beschäftigt.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:00
Es sind immer die ganz kleinen Fehler, die einen Stunden/Tagelang beschäftigen.
Gehe mal gedanklich einen Schritt zurück.

Ist es vielleicht irgendetwas banales?
Bspw: Mit XE5 erstellst du eine 32-Bit-DLL und mit XE7 unabsichtlich eine 64-Bit-DLL?
  Mit Zitat antworten Zitat
helste

Registriert seit: 16. Jul 2009
72 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:07
Ja, vielleicht ist es was banales, aber 64bit DLL ist es definitiv nicht.
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.126 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:28
Der Hintergrund ist der, dass ich neue Programmteile in Delphi XE (derzeit XE7) programmiere, aber das Hauptprogramm immer noch mit Delphi 2007 warten muss. Geht einfach nicht, das alles mit vertretbarem Aufwand umzustellen.
Genau so mache ich es - aus den gleichen Gründen - auch!

Übergibst Du ggf. Strings?
  Mit Zitat antworten Zitat
helste

Registriert seit: 16. Jul 2009
72 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:34
Ich konnte jetzt ein Szenarium erstellen, welches den Fehler bringt.
Das Ergebnis ist merkwürdig.

So sieht die DLL aus:

Code:
library testdll;

uses
  System.SysUtils,
  System.Classes,
  Winapi.Windows,
  dlltestunit in 'dlltestunit.pas' {Form1};

{$R *.res}

function edittest : HWND; stdcall;

begin
result := edit_test;
end;


exports
  edittest;

begin
end.

In der dlltestunit habe ich ein Formular, auf welches ich Datenbankkomponenten von IBDAC platziert habe. Dazu noch eine TFileSaveDialog Komponente.
Dann noch 3 Schalter, welche unterschiedliche Aktionen ausführen.

Der Source sieht dann so aus:

Code:
unit dlltestunit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Data.DB, MemDS, DBAccess,
  IBC;

type
  TForm1 = class(TForm)
    FileSaveDialog1: TFileSaveDialog;
    Button1: TButton;
    Label1: TLabel;
    IBCConnection1: TIBCConnection;
    IBCTransaction1: TIBCTransaction;
    IBCQuery1: TIBCQuery;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

function edit_test : HWND;

implementation

{$R *.dfm}

function edit_test : HWND;

var
  Form1: TForm1;

begin
result := 0;
Form1 := TForm1.Create (nil);
if assigned (Form1) then
   begin
   result := Form1.Handle;
   Form1.Show;
   end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
IBCQuery1.Open;
if not IBCQuery1.Eof then
   Label1.Caption := IBCQuery1.FieldByName('testfield').AsString;;
IBCQuery1.Close;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if FileSaveDialog1.Execute then
   Label1.Caption := FileSaveDialog1.FileName;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if FileSaveDialog1.Execute then
   begin
   Label1.Caption := FileSaveDialog1.FileName;
   IBCQuery1.Open;
   if not IBCQuery1.Eof then
      Label1.Caption := Label1.Caption + ' - ' + IBCQuery1.FieldByName('testfield').AsString;;
   IBCQuery1.Close;
   end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
IBCQuery1.SQL.Text := 'Select testfield from testtable';
end;

end.

Im Rufenden Programm habe ich ebenfalls eine kleine Maske gemacht, auf der sich 3 Schalter befinden.
Die clicke ich dann der Reihe nach an, wodurch zuerst die DLL initiailsiert wird, dann die Funktion aufgerufen wird (maske der DLL wird angezeigt und da wird dann einer der 3 Schalter gedrückt). Anschließend wird die Maske der DLL geschlossen und im rufenden Programm der 3 Button gedrückt um die DLL wieder frei zu geben.
Dann wird das Programm beendet.

Hier nun noch das rufende Programm (bzw. die Unit mit dem Form).

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Menus, StdCtrls;

type
  Tmain = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
     h       : HWND;
     testdll : HMODULE;
     edittest : function : HWND; stdcall;
  end;

var
  main: Tmain;

implementation

{$R *.dfm}


procedure Tmain.Button1Click(Sender: TObject);

begin
testdll := LoadLibrary('testdll.dll');
if testdll <> 0 then
   begin
   @edittest := GetProcAddress(testdll, 'edittest');
   end;
end;

procedure Tmain.Button2Click(Sender: TObject);

begin
if h = 0 then
   h := edittest
else
   ShowWindow(h, SW_SHOWNORMAL);
end;

procedure Tmain.Button3Click(Sender: TObject);

begin
FreeLibrary(LHnd);
edittest := nil;
end;

end.
Ich hoffe, das ist soweit verständlich.

Ich beobachte nun folgendes:

Drückt man in der aufgerufenen Maske (die aus Unit dlltestunit, also aus der aufgerufenen DLL Funktion) jeweils einen Button und beendet dann, dann passiert folgendes.
Bei Button1 und Button2 läuft alles völlig normal ab.
bei Button3 jedoch, läuft auch alles normal bis zum beenden des Hauptprogrammes. Das bleibt dann nämlich hängen und muss in der IDE durch den Programm abbrechen Button beendet werden. Startet man es außerhalb der IDE muss man den Taskmanager bemühen.

Es sieht also so aus: Ein Datenbankaufruf alleine macht nichts. FileSaveDialog1.Execute alleine macht ebenfalls nichts. Beides zusammen bringt Probleme.

Das ist nur eines von vielen Beispielen, wo das Problem auftritt. Einfaches Weglassen von FileSaveDialog1.Execute bringt mich also nicht weiter. In anderen Modulen ist es wieder ganz was anderes.

Jemand eine Idee?
  Mit Zitat antworten Zitat
helste

Registriert seit: 16. Jul 2009
72 Beiträge
 
Delphi 10.1 Berlin Professional
 
#8

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:45
Übergibst Du ggf. Strings?
Nein, in dem Beispiel nicht.

In meiner realen Anwendung übergebe ich auch Strings, aber nicht direkt, sondern in einem Datenkonstrukt.
Sieht dann z.B. so aus:
Code:
tparameter = record
              stringvar1,
              stringvar2  : pwidechar;
              intvalue1,
              intvalue2   : integer;
           end;
pparameter = ^tparameter;

var
   parameter : tparameter;
Übergeben wird dann ein Pointer.
In der DLL sieht das dann so aus:

Code:
function edittest (par : pparameter) : HWND; stdcall;

begin
.....
end;
Und aufgerufen wird es so:

Code:
function edittest (par : pparameter) : HWND; stdcall; external 'testlib.dll';

procedure testaufruf;

var
   par : tparameter;

begin
par.stringvar1 := 'aaa';
par.stringvar2 := 'bbb';
par.intvalue1 := 1;
par.intvalue1 := 2;
edittest (@par);
end;
Das funktioniert einwandfrei.
Verwende ich z.B. um Parameter für die Datenbank zu übergeben.
  Mit Zitat antworten Zitat
ringli

Registriert seit: 7. Okt 2004
504 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:53
FreeLibrary(LHnd); Mir fällt auf das du hier LHnd freigibst, dieses aber nirgendwo deklariert ist. Müsste das nicht eher FreeLibrary(testdll); lauten?
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.142 Beiträge
 
Delphi 12 Athens
 
#10

AW: DLL Problem mit XE7

  Alt 8. Apr 2015, 16:58
FreeLibrary ... siehe mein Vorredner.



Versuch mal tparameter = packed record und wenn die DLL Strings rausgibt, dann hoffe ich die werden nicht bei Prozedurende freigegeben.

Die VCL in einer DLL ist aber keine sonderlich gute Idee und kann natülich auch manchmal Probleme bereiten (außer vielleicht in einem eigenem Thread laufend), denn wenn man z.B. mal in TApplication.ProcessMessage reinsieht, dann erkennt man, daß dann Einiges an Funktionalität fehlt, bzw. Schief laufen kann, wenn die Messages nicht im eigenem Modul verarbeitet werden.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 8. Apr 2015 um 16:58 Uhr) Grund: *schnarch*
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 23:24 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