Aplikacja bazodanowa w dll

0

W tej bajce za udział biorą: Delphi, MySql i Zeos.

Postanowiłem sobie skomplikować życie i wsadzić działającą aplikację bazodanową do dll'ki.

  1. Kiedy trzymam wszystkow w exe scenariusz wygląda mniej więcej tak:
  • DataModule i w nim kontrolki do komunikacji z bazą,
  • forma i kotrolki wizualne z serii DB... w których wyklikuję sobie DataSource i DataField, no i jest miło i sympatycznie.
    To samo chciałem zastosować w dll'u, wyklikuję DataSource i dane się pojawiają... do momentu uruchomienia programu, DataSource się gubi (a dla zQuery gubi się Connection). Oczywiście przypisuję to z powrotem w onCreate formy ale czy to taki urok dll i tak ma być czy to ja coś spaprałem?
  1. Przy zamykaniu aplikacji otrzymuję 'Runtime error 216' i debuger wskazuje na AV w libmysql50.dll, wydaje się że problem jest przy zwalnianu DataModule.

initialization
DM := TDM.Create(nil);
finalization
DM.Free;

Kiedy sekcję finalization pozostawię pustą lub do DM przypiszę nil błędu nie ma.
Jak powinno wyglądać zwalnianie DM?

0

może byś tak coś więcej napisał - co jest w exe a co w dll, co i jak przekazujesz między dll i exe

0

Za wiele na razie nie mam bo to wstępne przymiarki do przełożenia aplikacji do dll.
Założenie było takie aby wszystko wsadzić do dll i dopisać mały program inicjujący, niestety poległem na tworzeniu formy fsMDIForm w dll'u więc wygląda to tak że w exe mam fsMDIForm a w dll DataModule i fsMDIChild (reszta w planach);

DLL

 
library formDll;

uses
  ShareMem,
  Forms,
  SysUtils,
  Classes,
  Windows,
  uMain in 'uMain.pas' {frmMain}, // to miał być fsMDIForm
  uDM in 'uDM.pas' {DM: TDataModule},
  uTable in 'uTable.pas' {frmTable},
  uShare in 'uShare.pas';

{$R *.res}


procedure MyDLLProc(Reason: Integer); stdcall;
begin
  if Reason = DLL_PROCESS_DETACH then
  if Assigned(DllApp) then
  begin
    Application := DllApp;
    Screen := DllScreen;
  end;
end;

exports
  ShowMain name 'ShowMain',
  MyDllProc name 'MyDllProc';

begin

end.
unit uShare;

interface

uses
   Windows, Forms, Dialogs, SysUtils, Classes;

var
  DllApp : TApplication;
  DllScreen : TScreen;

  procedure ShowMain(App : TApplication; Scr : TScreen); stdcall;

exports
  ShowMain;

implementation

Uses uTable, uDM;


procedure ShowMain(App : TApplication; Scr : TScreen); stdcall;
begin
  if not Assigned(DllApp) then
  begin
    DllApp := Application;
    DllScreen := Screen;
    Application := App;
    Screen := Scr;
  end;
  if not DM.DataBase.Connected then // DataBase = ZConnection
    DM.DataBase.Connect;
  DM.qZ.Open;
  frmTable := TfrmTable.Create(Application);
  frmTable.Show;
  frmTable.DBGrid1.DataSource := DM.dsZ;
  frmTable.DBEdit1.DataSource := DM.dsZ;
  frmTable.DBEdit1.DataField := 'nazwisko';
end;

end.
 

W DataModule tylko sekcje initialization/finalization.

EXE

 
...
var
  Form1: TForm1;
  procedure ShowMain(App : TApplication; Src : TScreen); stdcall external 'formDll.dll' name 'ShowMain';
  procedure MyDLLProc(Reason: Integer); stdcall external 'formDll.dll' name 'MyDllProc';

implementation

  

{$R *.dfm}

procedure TForm1.Show1Click(Sender: TObject);
begin
  ShowMain(Application, Screen);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  i : integer;
begin
  for I := 0 to MDIChildCount -1 do
    begin
      MDIChildren[i].Free;
    end;
  MyDllProc(DLL_PROCESS_DETACH);
end;

end.
0

do dll nie przekazuje się obiektów i stringów a jedynie typy proste.
Najprostsze pytanie - po co chcesz to robić? Jak dla zabawy to zainteresuj się interfejsami i/lub bplami. Jak musisz bo Ci kazali to po pierwsze nie przekazujesz app i scr jako TApplication i TScreen a jako integer a w dll rzutujesz odpowiednio na TApplication i TScreen.
Po co to jest

for I := 0 to MDIChildCount -1 do
    begin
      MDIChildren[i].Free;
    end;
0
Delphi napisał(a)
{ Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. }
Misiekd napisał(a)

Jak musisz bo Ci kazali to po pierwsze nie przekazujesz app i scr jako TApplication i TScreen a jako integer a w dll rzutujesz odpowiednio na TApplication i TScreen.
Sądzę że to bez znaczenia.

0
Misiekd napisał(a)

Najprostsze pytanie - po co chcesz to robić?

Wymyśliłem sobie automagiczną aktualizację - podmiana dll'a wydawała mi się najprostsza.

Misiekd napisał(a)

Po co to jest

for I := 0 to MDIChildCount -1 do
    begin
      MDIChildren[i].Free;
    end;

Zwalniam Childy utworzone w dll.

0

<quote=Azarien>

Delphi napisał(a)

<delphi>{ Important note about DLL memory management: ShareMem must be the first unit in your library's ...

ShareMem jest na pierwszym miejscu.

0
pytek napisał(a)

Wymyśliłem sobie automagiczną aktualizację - podmiana dll'a wydawała mi się najprostsza.
najprościej to jest napisać malutkiego exeka, który odpali się najpierw (albo jak program główny wykryje, że jest nowa wersja), ściągnie nową wersję i odpali program główny

Zwalniam Childy utworzone w dll.
Childy się same zamkną i zwolnią trzeba im tylko w OnClose wstawić Action := caFree;

0

OK, Childy już sięsame zamykają.

Misiekd napisał(a)

... nie przekazujesz app i scr jako TApplication i TScreen a jako integer a w dll rzutujesz odpowiednio na TApplication i TScreen.

Zmieniłem tak jak radziłeś ale to nie rozwiązuje problemu zgubionych DataSource :/

0

Gdyby ktoś znał rozwiązanie zagadki znikających DataSource to chętnie się zapoznam, na razie przechodzę na bpl - wygląda obiecująco.

1 użytkowników online, w tym zalogowanych: 0, gości: 1