Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Class in DLL verwenden (https://www.delphipraxis.net/169864-class-dll-verwenden.html)

little_budda 16. Aug 2012 20:04

Delphi-Version: 2007

Class in DLL verwenden
 
Hallo.

Ich versuche gerade Code von meiner Anwendung in eine DLL zu verfrachten.
Es ist meine erste DLL.
Ich habe daa Tutorial von Assarbad gelesen und fand die Iddee ganz velockend.

Nun zu meinem Problem.

Ich möchte einen Typ der Klasse TDataModule verwenden.
Meine Deklaration sieht bisher so aus

Delphi-Quellcode:
library wsatools;

uses Windows, ShellAPI, Messages, Classes, SysUtils, Graphics, Controls,
      StdCtrls, ComCtrls, DB, ExtCtrls, XMLDoc, XMLIntf, DBTables, ADODB,
      ...

type
  TDataModule2 = class(TDataModule)
    Table1ZEIT: TStringField;
    Table1QUELLE: TStringField;
    Table1ZsLen: TStringField;
    Table1MNR: TStringField;
    Table1Spez: TStringField;
    Table1ZUSTAND: TStringField;
    Table1ZSINFO: TStringField;
    DataSource1: TDataSource;
    Table1: TTable;
    Table1IDX: TStringField;
    ADOConnectionTexte: TADOConnection;
    ADOQueryTexte: TADOQuery;

    procedure Table1ZEITGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1ZSINFOGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1QUELLEGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1SpezGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1ZUSTANDGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1ZsLenGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1MNRGetText(Sender: TField; var Text: String; DisplayText: Boolean);
    procedure Table1IDXGetText(Sender: TField; var Text: String; DisplayText: Boolean);
end;
Als Variable habe ich angelegt
Delphi-Quellcode:
var
  ...
  DataModule2: TDataModule2;
Wenn ich jetzt darauf zugreifen möchte bekomme ich immer eine Exeption weil "DataModule2" nil ist.
Delphi-Quellcode:
function ExtractArchiveContentToTable (fullArchivePath : string) : integer;
var ...
begin
  DataModule2.Table1.Active := FALSE;
  DataModule2.Table1.Tablename := ExtractFileName(fullArchivePath);
  DataModule2.Table1.DatabaseName := ExtractFileDir(fullArchivePath);
  ...
Muss ich da noch einen Konstruktor oder ähnliches aufrufen?
Warum klappt das in einer WinForms Anwendung?

:?:

Vielleicht hat ja jemand einen Tipp für mich.
Gruß Holger.

himitsu 16. Aug 2012 23:12

AW: Class in DLL verwenden
 
Zitat:

Zitat von little_budda (Beitrag 1178536)
Muss ich da noch einen Konstruktor oder ähnliches aufrufen?
Warum klappt das in einer WinForms Anwendung?

Natürlich?

Willst du auf ein Objekt der Klasse zugreifen, dann mußt du erstmal ein instanziertes Objekt dieser Klasse erstellen, was man irdentwo mit Create macht.

Grundsätzlich ist die Vorgehensweise in DLL und EXE (VCL, NonVCL oder Konsole) die Selbe.

PS: Wenn du eine Form oder DataModul erstellst, dann kann man die VCL in einem VCL-Projekt (neuerdings auch FMX statt VCL) dazu bringen diese Instanzen "automatisch" erstellen zu lassen, welches standardmäßig "aktiviert" wird, wenn man diese Units automatisch generieren läßt.
siehe Projekt-Optionen > Formulare

bzw. siehe Projekt-Datei (DPR), denn da werden letztendlich diese Instanten erstellt. Siehe
Delphi-Quellcode:
Application.CreateForm(...)
, worin das Create aufgerufen wird.


Du mußt also letzendlich deine Instanz des DataModuls irgendwo "selbst" erstellen.
> über eine Initialize-Prozedur, welche deine EXE anfangs erstmal aufrufen muß, bevor sie due Funktionen der DLL nutzen darf
> im Initialization-Abschnitt einer Unit (in Finalization natürlich wieder freigeben)
> in einem Class-Constructor der Klasse (ist das "Gleiche" wie Initialization/Finalization)
> im Begin-End-Bereich des DLL-Projekts (DPR), aber dort fehlt dann die Freigabe-Stelle der Instanz



PS: Das automatische Generieren aller Forms/DataModule ist auch nicht immer das Wahre.
Stell dir mal vor Delphi oder MS Word würde alle Fenster immer gleich bei Programmstart erstellen, dann bräuchten diese ewig zum Starten und würden immer extrem Arbeitsspeicher belegen, was vorallem dann sinnlos ist, wenn etwas selten verwendet wird ... Darum erstellt man da viele Vormulare "manuell" erst dann, wenn sie benötigt werden und gibt sie danach gleich wieder frei.

little_budda 17. Aug 2012 07:56

AW: Class in DLL verwenden
 
Super, danke dir.
Nachdem ich das Problem mit "CoInitalize" noch gelöst habe,
klappt es hervorragend.

Ich habe in meiner DLL dazu noch eine "InitDLL" und eine "FreeDLL" Procedure angelegt.
Delphi-Quellcode:
uses
...
  ActiveX,
...

procedure InitDLL(window: Cardinal);
begin
  _hwnd := window;
  CoInitialize(nil);
  Application.CreateForm(TDataModule2, DataModule2);
end;


procedure FreeDLL(window: Cardinal);
begin
  CoUnInitialize();
end;

sx2008 17. Aug 2012 10:11

AW: Class in DLL verwenden
 
Teile der VCL werden doppelt vorhanden sein: zum Einen im Hauptprogramm und zum Anderen in der DLL.
Die EXE, die keine DLL verwendet wird also kleiner sein als die Summe der neuen EXE + DLL.

Deine EXE + DLL Lösung hat eigentlich nur Nachteile:
* grösser, benötigt mehr Resourcen
* schwieriger zu Debuggen
* meist höhere Ladezeit
* Probleme bei der Verarbeitung von Exceptions, da es die Exception Klassen nun zweimal gibt
* Probleme beim Updaten - es gibt verschiedene Versionen von EXE und DLL;
will man auf Nummer Sicher gehen muss man Beides schicken
* Entwicklungszeit verlängert sich

Unter Delphi sollte man keine DLLs erzeugen, die Teile der VCL benützen um die beschriebenen Probleme zu vermeiden.
Kurzgesagt: DLLs sollten Non-VCL sein!
Delphi Packages vermeiden zwar einige der Probleme, allerdings entstehen neue Probleme.
Du musst nun nämlich die Standard - Packages mitliefern und auf dem Zielrechner installieren.
Dabei besteht immer die Gefahr, dass schon eine andere Anwendung diese Packages installiert hat.
Sollte diese andere Anwendung deinstalliert werden, könnten auch die Packages gelöscht werden und deine Anwendung startet nicht mehr.

himitsu 17. Aug 2012 10:26

AW: Class in DLL verwenden
 
Man muß diese Packages nicht unbedingt installieren.
Einfach ins Programmverzeichnis gelegt, gibt es keine Versionskonflikte mit anderen Programmen, da jeder seine eigenen Dateien/Versionen besitzt.
(OK, dafür kann es vorkommen, daß die RTL/VCL-Dateien eventuell doppelt/mehrfach im System rumschwirren, wenn man mehrere Programme mit Packages dort installiert hat)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:54 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