![]() |
DLL + DataModule in Objektinspektor
Hi,
ich möchte gerne Teile meines Projekts in dlls auslagern. Dazu habe ich mir nun in einem Testprojekt folgendes erstellt: * eine Hauptform, die die DLL lädt * eine DatenModul-Klasse BaseDataModule = class(TDataModule) Die Hauptform erzeugt zur Laufzeit das DatenModul und bindet es unter public ein. (Die globale DataModule-Variable habe ich entfernt). In der DLL wird die Unit des DatenModuls eingebunden, damit die DLL die Unit überhaupt kennt. Die dll kann nun eine Form erzeugen und diese direkt mit dem DataModule verbinden. (Create umgeschrieben). Nungut - die DLL "kennt" das DatenModul also und kann ohne weiteres damit arbeiten. Zur Designzeit kennt die Form in der DLL das DataModule auch. Ich kann ohne Probleme z.B. ein DBGrid mit einem DataSource des DatenModuls verbinden. Starte ich das Programm, wird diese Bindung von Grid zum DataSource aber nicht wieder hergestellt. Das funktioniert leider nur zur Designzeit. Weiß jemand wieso? Ich kann bei umfangreicheren Dialogen schlecht immer wieder alles per SourceCode machen - will ja schließlich RAD nutzen :dancer: Achja: egal, wie ich das DatenModul in der Form in der dll nenne, im Objektinspektor kann immer über BaseDataModule darauf zugegriffen werden. Komisch das... :gruebel: Danke schon mal für eure Hilfe? :) Gruß |
Re: DLL + DataModule in Objektinspektor
Kann es sein, das die DLL das Problem ist?
Wenn ich ein Datenmodul in einer DLL verwende, nutze ich in der DLL.dpr immer folgende Routinen:
Delphi-Quellcode:
Ich habe das irgendwo aus dem Netz. Hoffe es hilft dir weiter.
library myDLL;
uses ShareMem, MyDatenmodul in 'MyDatemodul.pas' {MyDatenmodul: TDataModule}, ... resourcestring //-- Datenbank DLL Vorgaben ------------------------------------------------- dllPath = 'plugins'; //-- Datenbank DLL Fehlermeldungen ------------------------------------------ dllPathError = 'Der PlugIn Ordner %s konnte nicht erstellt werden'; dllCoInitError = '%s hat einen CoInitialize-Fehler gemeldet!'; dllDMCreateError = '%s hat einen Fehler beim Erzeugen des Datenmoduls %s gemeldet!'; {$R *.RES} var DLLProcNext : procedure(Reason: Integer); stdcall = nil; bDoCoUninitialize : Boolean; bDoDestroyDM_ADO : Boolean; // ============================================================================ // Interne - Hilfsfunktionen // ============================================================================ // ---------------------------------------------------------------------------- // function DBInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Alle Eemente der DLL initialisieren bzw erzeugen // Parameter..: keine // Erreichbar.: intern function DBInit: boolean; stdcall; var sMsg: string; begin Result := true; try; //-- ActivX initialisieren ------------------------------------------------ sMsg:= Format(dllCoInitError, [dllName]); CoInitialize(nil); bDoCoUninitialize := True; //-- Datenmodul erzeugen -------------------------------------------------- sMsg:= Format(dllDMCreateError, [dllName, DatTable]); MyDatenmodul:= TMyDatemodul.Create(Application); except; ShowMessage(sMsg); Result := false; end; end; // ---------------------------------------------------------------------------- // function DBUnInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Datenmodul deinitialisieren // Parameter..: keine // Erreichbar.: intern function DBUnInit: boolean; stdcall; begin Result := true; bDoCoUninitialize := false; bDoDestroyDM_ADO := false; try if bDoDestroyDM_ADO then MyDatemodul.Free; if bDoCoUninitialize then CoUninitialize; except Result := false; end; end; // ---------------------------------------------------------------------------- // procedure DLLMain(Reason: Integer); stdcall; // ---------------------------------------------------------------------------- // Funktion...: eigene Strukturen und Objekte initialisieren // Parameter..: [Reason] == Grund des Aufrufs // Erreichbar.: intern procedure DLLMain(Reason: Integer); stdcall; begin case Reason of //-- Die DLL wurde in den Speicherbereich des akt. Prozesses geladen ------ DLL_PROCESS_ATTACH : begin DisableThreadLibraryCalls(hInstance); DBInit; end; //-- Der aktuelle Prozeß erzeugt einen neuen Thread ----------------------- DLL_THREAD_ATTACH : begin end; //-- Ein Thread wird beendet ---------------------------------------------- DLL_THREAD_DETACH : begin end; //-- Die DLL wird wieder aus dem Speicherbereich des akt.Prozesses entfernt DLL_PROCESS_DETACH : begin DBUnInit; end; end; if Assigned(DLLProcNext) then DLLProcNext(Reason); end; // ============================================================================ // Initialisierungscode // ============================================================================ begin DLLProcNext := Pointer(InterlockedExchange(Integer(DLLProc),Integer(@DLLMain))); DLLMain(DLL_PROCESS_ATTACH); end. |
Re: DLL + DataModule in Objektinspektor
Wenn du ein Package anstatt einer Dll verwendest hast du weinger Probleme.
BTW. wenn du Programteile dynamisch zulädst verlierst du zwwangsläufig zur Designzeit eingestellte Verbindungen. |
Re: DLL + DataModule in Objektinspektor
Zitat:
Alle Laufzeit BPL müssen mit ausgeliefert werden. Da kommen schnell mal an die 100 zusammen und wehe es sind nicht alls auf den neusten Stand. Gruß Peter |
Re: DLL + DataModule in Objektinspektor
Du kannst aber mehere bpls wiederrum in eine verpacken und diese dann ausliefern.
|
Re: DLL + DataModule in Objektinspektor
Zitat:
Gruß Peter |
Re: DLL + DataModule in Objektinspektor
Hallo,
ich habe mir jetzt schon mehrmals den kompletten Beitrag gelesen und komme nicht weiter. Ich habe auch versucht den Code hier :
Delphi-Quellcode:
in ein Beispielprojekt einzufügen. Nur leider bekomme ich beim Compilieren der DLL schon den Fehler, das dllname unbekannt sei. Was habe ich verkehrt gemacht ?
library myDLL;
uses ShareMem, MyDatenmodul in 'MyDatemodul.pas' {MyDatenmodul: TDataModule}, ... resourcestring //-- Datenbank DLL Vorgaben ------------------------------------------------- dllPath = 'plugins'; //-- Datenbank DLL Fehlermeldungen ------------------------------------------ dllPathError = 'Der PlugIn Ordner %s konnte nicht erstellt werden'; dllCoInitError = '%s hat einen CoInitialize-Fehler gemeldet!'; dllDMCreateError = '%s hat einen Fehler beim Erzeugen des Datenmoduls %s gemeldet!'; {$R *.RES} var DLLProcNext : procedure(Reason: Integer); stdcall = nil; bDoCoUninitialize : Boolean; bDoDestroyDM_ADO : Boolean; // ============================================================================ // Interne - Hilfsfunktionen // ============================================================================ // ---------------------------------------------------------------------------- // function DBInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Alle Eemente der DLL initialisieren bzw erzeugen // Parameter..: keine // Erreichbar.: intern function DBInit: boolean; stdcall; var sMsg: string; begin Result := true; try; //-- ActivX initialisieren ------------------------------------------------ sMsg:= Format(dllCoInitError, [dllName]); CoInitialize(nil); bDoCoUninitialize := True; //-- Datenmodul erzeugen -------------------------------------------------- sMsg:= Format(dllDMCreateError, [dllName, DatTable]); MyDatenmodul:= TMyDatemodul.Create(Application); except; ShowMessage(sMsg); Result := false; end; end; // ---------------------------------------------------------------------------- // function DBUnInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Datenmodul deinitialisieren // Parameter..: keine // Erreichbar.: intern function DBUnInit: boolean; stdcall; begin Result := true; bDoCoUninitialize := false; bDoDestroyDM_ADO := false; try if bDoDestroyDM_ADO then MyDatemodul.Free; if bDoCoUninitialize then CoUninitialize; except Result := false; end; end; // ---------------------------------------------------------------------------- // procedure DLLMain(Reason: Integer); stdcall; // ---------------------------------------------------------------------------- // Funktion...: eigene Strukturen und Objekte initialisieren // Parameter..: [Reason] == Grund des Aufrufs // Erreichbar.: intern procedure DLLMain(Reason: Integer); stdcall; begin case Reason of //-- Die DLL wurde in den Speicherbereich des akt. Prozesses geladen ------ DLL_PROCESS_ATTACH : begin DisableThreadLibraryCalls(hInstance); DBInit; end; //-- Der aktuelle Prozeß erzeugt einen neuen Thread ----------------------- DLL_THREAD_ATTACH : begin end; //-- Ein Thread wird beendet ---------------------------------------------- DLL_THREAD_DETACH : begin end; //-- Die DLL wird wieder aus dem Speicherbereich des akt.Prozesses entfernt DLL_PROCESS_DETACH : begin DBUnInit; end; end; if Assigned(DLLProcNext) then DLLProcNext(Reason); end; // ============================================================================ // Initialisierungscode // ============================================================================ begin DLLProcNext := Pointer(InterlockedExchange(Integer(DLLProc),Integer(@DLLMain))); DLLMain(DLL_PROCESS_ATTACH); end. |
Re: DLL + DataModule in Objektinspektor
Du hast nichts falsch gemacht.
Als ich den Code aus einem Project von mir kopiert und hier eingefügt habe, vergass ich die beiden Constanten zu erwähnen. Also, ich glaube hier hast du den Fehler bekommen.
Delphi-Quellcode:
dllName : ist eine String Konstante mit dem Dateinamen der DLLsMsg:= Format(dllDMCreateError, [dllName, DatTable]); DatTable : ist eine String Konstante mit dem Namen der Tabelle in der Datenbank Ich hoffe, das hilft dir jetzt weiter. |
Re: DLL + DataModule in Objektinspektor
Also, wenn ich das ganze jetzt richtig verstehe, dann kann ich über diese Weise die Parameter meiner Komponenten in dem DataModule nicht füllen oder ? Denn ich möchte in meinem Programm mich auf verschiedene Datenbanken und Datenbanktypen verbinden. Das heißt, ich möchte gerne meine Verbindungsparameter an die Komponente ZConnection übergeben und die ZQuery soll mir dann die SQL-Befehle ausführen.
Kann ich das über diese Weise machen oder nicht ? Wenn ja, wie muss ich das machen ? |
Re: DLL + DataModule in Objektinspektor
Wenn du den Code in einer Komponente verwenden willst, kannst du ein Feld für den DLL-Namen und ein Feld für die Tabelle vorsehen. Anstelle der String-Konstanten werden dann in der Fehlermeldung halt die Werte der Felder angezeigt.
Du kannst auch die Fehlermeldungen aus dem Code nehmen und darauf hoffen, das es ohne Fehler läuft.
Delphi-Quellcode:
Ein Problem stellt noch die Verwendung von ShareMem dar. Wenn du eine Komponente entwickelst, muss dem Anwender mitgeteilt werden, das er im Projekt die Unit ShareMem in der Projekt Datei einbinden muss. Ansonsten kommt es zu nicht nachzuvollziehbaren Fehlern.
library myDLL;
uses ShareMem, MyDatenmodul in 'MyDatemodul.pas' {MyDatenmodul: TDataModule}, ... {$R *.RES} var DLLProcNext : procedure(Reason: Integer); stdcall = nil; bDoCoUninitialize : Boolean; bDoDestroyDM_ADO : Boolean; // ============================================================================ // Interne - Hilfsfunktionen // ============================================================================ // ---------------------------------------------------------------------------- // function DBInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Alle Eemente der DLL initialisieren bzw erzeugen // Parameter..: keine // Erreichbar.: intern function DBInit: boolean; stdcall; begin Result := true; try; //-- ActivX initialisieren ------------------------------------------------ CoInitialize(nil); bDoCoUninitialize := True; //-- Datenmodul erzeugen -------------------------------------------------- MyDatenmodul:= TMyDatemodul.Create(Application); except Result := false; end; end; // ---------------------------------------------------------------------------- // function DBUnInit: Integer; stdcall; // ---------------------------------------------------------------------------- // Funktion...: Datenmodul deinitialisieren // Parameter..: keine // Erreichbar.: intern function DBUnInit: boolean; stdcall; begin Result := true; bDoCoUninitialize := false; bDoDestroyDM_ADO := false; try if bDoDestroyDM_ADO then MyDatemodul.Free; if bDoCoUninitialize then CoUninitialize; except Result := false; end; end; // ---------------------------------------------------------------------------- // procedure DLLMain(Reason: Integer); stdcall; // ---------------------------------------------------------------------------- // Funktion...: eigene Strukturen und Objekte initialisieren // Parameter..: [Reason] == Grund des Aufrufs // Erreichbar.: intern procedure DLLMain(Reason: Integer); stdcall; begin case Reason of //-- Die DLL wurde in den Speicherbereich des akt. Prozesses geladen ------ DLL_PROCESS_ATTACH : begin DisableThreadLibraryCalls(hInstance); DBInit; end; //-- Der aktuelle Prozeß erzeugt einen neuen Thread ----------------------- DLL_THREAD_ATTACH : begin end; //-- Ein Thread wird beendet ---------------------------------------------- DLL_THREAD_DETACH : begin end; //-- Die DLL wird wieder aus dem Speicherbereich des akt.Prozesses entfernt DLL_PROCESS_DETACH : begin DBUnInit; end; end; if Assigned(DLLProcNext) then DLLProcNext(Reason); end; // ============================================================================ // Initialisierungscode // ============================================================================ begin DLLProcNext := Pointer(InterlockedExchange(Integer(DLLProc),Integer(@DLLMain))); DLLMain(DLL_PROCESS_ATTACH); end.
Delphi-Quellcode:
Ich habe bei mir nur eine Unit für die Allgemeine Verwendung des DM in einer DLL geschrieben. Die füge ich zu meinem Project hinzu, lege ein DM an und arbeite dann wie gewohnt in der IDE. Die DLL-Namen und Tabellen-Konstanten lege ich in einer Res oder Inc Datei ab, die ich mit folgendem Aufruf in das Project mit einbinde.
program netguide;
uses ShareMem, Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end.
Delphi-Quellcode:
Ich hoffe, das hilft dir weiter.
{$I 'meineKonstanten.inc'}
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:13 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz