06. oktober 2012 - 15:28Der 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... )
Teknologi, AI og forretning er i centrum på Computerworlds Cloud og AI Festival i København d. 18. og 19. september. Se hele programmet for den store konference om strategisk brug af Cloud og AI på: www.cloud-festival.dk
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.
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?
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.
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?
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;
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
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.
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.
Jeg skulle have lagt et svar herover - ellers er der svar her ;-)
Synes godt om
Ny brugerNybegynder
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.