06. oktober 2012 - 15:28 Der er 8 kommentarer og
1 løsning

Kald af DLL fra en DLL

HEJ,

Jeg har en programstump, som kalder en DLL.

(Denne DLL er en kalender, som returnerer en TRecord, med valgte dato, ugenummer, dagens nummer (valgte dato) og dato på mandagen i valgte uge). Dette fordi min Delphi har lidt problemer med at returnere Strings. (jeg ved jeg kan bruge PChar, men det her fungerer upåklageligt)

Nu har jeg brug for at udvide denne DLL lidt (konfigureringsdata).

Jeg har prøvet om jeg kunne kalde en konfigurerings-form fra DLL'en, men det giver mig en ACCESS fejl.

Så spørgsmålet er, om jeg kan kalde en ny DLL (med form) fra denne Calender-DLL ?      (og så hælde de relevante konfigureringsdata data i en TRecord og få data tilbage i samme TRecord. )

HVIS JA :
Hvad er antallet af sub-levels på dette DDL -kald (altså kan denne nye DLL igen kalde en ny DLL --- og så fremdeles... )


Kristian

Kristian
Avatar billede arne_v Ekspert
06. oktober 2012 - 15:32 #1
Jeg tror ikke at der er nogen generel begraensning paa dybden af DLL dependencies - hvis du bruger en dependency walker vil se at mange DLL allerede har meget dybe dependency traer.

Det er imidlertid ikke det samme som at dit projekt vil vaere nemt at lave.

Der kan godt vaere problemer med f.eks. en GUI DLL som forventer at COM environment er sat op paa en bestemt maade.
Avatar billede friiiiis Novice
12. oktober 2012 - 10:09 #2
hmmm... Arbejder meget med DLL filer og det giver næsten aldrig problemer...

Problemet med DLL filer og form plejer at være den måde man kalder Formen i DLL filen; altså hvordan du CREATE formen og efterfølgen FREE formen - kan du sende nogle kodelinjer, herunder specielt hvordan man kalder DLL filen samt hvordan du opretter formen?
12. oktober 2012 - 19:01 #3
HEJ,

Tak for responsa.

Mit problem er:

MAINFORM kalder en DLL_1  med en form. Denne (DLL-form) skal kalde 2 DLL'er (en kalender (form, returnerer en TRecord, med data (denne virker) og en Navne-form (bruger indsætter navn, adresse, osv) og vælger en FARVE som "skille-tegn" (hver bruger sin farve / for at undgå forvekslinger).

MANIFORM kalder en ny DLL_2, som kalder en regulær form. Denne (regulære ) for kalder BEGGE DLL (kalender og NAVNe-DLL) (dog ikke samtidigt).

Når MAINform kalder DLL-1 kan MAINFORM IKKE kalde DLL-2 og vice-versa

Jeg ved jeg kunne lave det som ordinære FORMS, men det er dels for at lære at bruge DLL'ere og fordi de senere skal kunne skiftes UDEN at opdatere HELE programmet.

KRISTIAN
Avatar billede friiiiis Novice
13. oktober 2012 - 12:48 #4
1) Send nogle kodelinjer
2) Spor dig ind på problemet: Prøv at simplificer problemet så du med så få og med så simple DLL filer kan fremkalde problemet.
3) Husker du at lave Freelibrary hver gang (VIGTIGT!!) du er færdig med en DLL ?
4) Hvad er fejlen - altså hvad er det for en exception der opstår?
16. oktober 2012 - 16:05 #5
HEJ

HER er Selve DLL'en (eller dele af den):

library BehLib;

uses
  ShareMem, SysUtils, Classes,
  BehLibUnit in 'BehLibUnit.pas' {BehLibForm};

{$R *.res}

Exports
  BehShowForm;


begin
end.


Og her er BEHLIBFORM:

unit BehLibUnit;

interface

uses
  ShareMem, Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs;

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

var
  BehLibForm: TBehLibForm;

{ Declare the export function }
function BehShowForm (AHandle: THandle; ACaption: String): Integer; StdCall;

implementation
{$R *.DFM}

function BehShowForm(AHandle: THandle; ACaption: String): Integer;
var
  BehLibForm: TBehLibForm;
begin
  // Copy application handle to DLL's TApplication object
  Application.Handle := AHandle;
  BehLibForm  := BehLibForm.Create(Application);
  try
    BehLibForm.Caption := ACaption;
    BehLibForm.ShowModal;

    Result := 1;
  finally
    BehLibForm.Free;
  end;
end;

end.

Result'et fra behform er sat til 1 (Integer) men mainformen herunder modtager IKKE denne INTEGER. Aner ikke hvad der er galt?






VAR
  RetInt : Integer;


procedure TMainForm.Button2Click(Sender: TObject);
var
  LibHandle  : THandle;
  BehShowForm : TBehShowForm;

begin
  { Attempt to load the DLL }
  LibHandle := LoadLibrary('BehLib.dll');
  try
      if LibHandle = 0 then
        raise EDLLLoadError.Create('Unable to Load DLL');
      @BehShowForm := GetProcAddress(LibHandle, 'BehShowForm');
      if not (@BehShowForm = nil) then
        BEGIN
            RetInt := BehShowForm(Application.Handle, Caption);
           
            (* Fejlen opstår her, idet RetInt ikke er defineret, påstår den ! *)
 
            showmessage('retur fra DLL ' + inttostr(retint));
        END
      else
        BEGIN
            ShowMessage('TEST 3 ');
        END;
  finally
      FreeLibrary(LibHandle); // Unload the DLL.
  end;
end;
Avatar billede friiiiis Novice
16. oktober 2012 - 19:33 #6
Du har placeret "function BehShowForm(AHandle: THandle; ACaption: String): Integer;"

inde i din form...

Det betyder at når du kalder din DLL så er din form ikke initialiseret - og det bliver den heller ikke fordi der ikke er en "BehLibForm.Create(Application);" i selve DLL Library

Lige om 5 minutter sender jeg en kode der burde virke
Avatar billede friiiiis Novice
16. oktober 2012 - 19:50 #7
Følgende virker hos mig:

//=============================
// Dette er din exe fil hvoirfra du kalder din DLL

unit Unit10;

interface

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

type
  TForm10 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure InitiateDLLHandle;
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    DLLHandle_BehShowForm : THandle;
    DLLHandle_BehShowForm_BOOL : Boolean;
    BehShowForm : function(ParentApplication:TApplication): integer; stdcall;

  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

procedure TForm10.Button1Click(Sender: TObject);
begin

  try
    InitiateDLLHandle;
    if DLLHandle_BehShowForm_BOOL then
      showmessage('Retur fra DLL=' + inttostr(BehShowForm(Application)));
  finally
    FreeLibrary(DLLHandle_BehShowForm); // Unload the DLL.
    DLLHandle_BehShowForm_BOOL := false;
  end;
end;


procedure TForm10.FormShow(Sender: TObject);
begin
DLLHandle_BehShowForm_BOOL := false;
end;

procedure TForm10.InitiateDLLHandle;
var
  s :string;
  sFile :string;
  sTest :string;
  sRunTime :string;
begin

sFile := 'BehLib.dll';
sTest := 'C:\Documents and Settings\HHF\Dokumenter\RAD Studio\Projects\Test 26 Snestrup 2000\DLL\' + sFile;
sRunTime := ExtractFileDir(application.ExeName) + '\' + sFile;

if not DLLHandle_BehShowForm_BOOL then
  begin
    if fileexists(sTest) then
      s := sTest
    else
      s := sRunTime;

if not DLLHandle_BehShowForm_BOOL then
  begin
    DLLHandle_BehShowForm := LoadLibrary(PChar(s));
    if (DLLHandle_BehShowForm < HINSTANCE_ERROR) then
      begin
        raise Exception.Create(s + ' library can not be loaded or not found. ' + SysErrorMessage(GetLastError));
      end;

    try
    { load an address of required procedure}
    if DLLHandle_BehShowForm <> 0 then
    @BehShowForm := GetProcAddress(DLLHandle_BehShowForm, 'BehShowForm');
    if Assigned(BehShowForm) then
      DLLHandle_BehShowForm_BOOL := true;
    except
      on exception do
      raise Exception.Create(s + ' library can not be loaded or not found. ' + SysErrorMessage(GetLastError));
    end;
  end;
  end;
 
end;
end.


//==========================================
//==========================================
//==========================================
// Dette er din DLL fil

library BehLib;

{ 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. }

uses
  SysUtils,
  Classes,
  Forms,
  windows,
  ACtiveX,
  UBehLibForm in 'UBehLibForm.pas' {BehLibForm};

var
  DllApplication : TApplication;
{$R *.RES}

function BehShowForm(ParentApplication:TApplication): integer; stdcall;
begin
  Application := ParentApplication;
  coinitialize(nil);
  BehLibForm := TBehLibForm.Create(nil);
  BehLibForm.Showmodal;
  Result := BehLibForm.UpDown1.Position;
  //Result := Form1.Heltal;
  BehLibForm.free;
end;


procedure DLLUnloadProc(Reason: Integer); register;
begin
  if Reason = DLL_PROCESS_DETACH then
    Application := DllApplication;
end;

exports
  BehShowForm;

begin
DllApplication := Application;
DLLProc := @DLLUnloadProc;
end.


//=================
//=====================================

// Dette er formen i din DLL fil

unit UBehLibForm;

interface

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

type
  TBehLibForm = class(TForm)
    Edit1: TEdit;
    UpDown1: TUpDown;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  BehLibForm: TBehLibForm;

implementation

{$R *.dfm}

end.
17. oktober 2012 - 15:35 #8
HEJ,

Tak for koden.

Den fungerer osse hos mig, men er lidt mere kompliceret end det jeg havde tænkt mig. 

Men noget positivt kom der ud af det. Fordi jeg gennemgik min kode minutiøst, sammenlignede bogstav for bogstav (syntaktisk og semantisk) med eklsisterende kode og fandt faktisk ud af hvad det var jeg havde lavet  forkert. Så jeg rettede og viola (fransk for Voilá ), koden kørte. 

Så der er point .

Send et svar og du er (point) rigere.

kristian
Avatar billede friiiiis Novice
17. oktober 2012 - 16:02 #9
Jeg skulle have lagt et svar herover - ellers er der svar her ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester