15. august 2003 - 13:17Der er
19 kommentarer og 1 løsning
Loadning af dll, fejl
Jeg har en dll fil med navnet "projekt1dll.dll"
kode til den er
-- start --
library Project1dll;
{ Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select View-Project 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 DELPHIMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using DELPHIMM.DLL, pass string information using PChar or ShortString parameters. }
uses SysUtils, Classes;
Function Mitnavn( X: Integer ): STRING; EXPORT Begin If x = 1 then Mitnavn := 'Dennis' Else Mitnavn := 'Hejhej' End;
procedure TForm1.Button1Click(Sender: TObject); var GetMitNavn: Function ( X: Integer ):STRING;
begin DLLHandle := LoadLibrary('Project1dll.dll'); if Handle <> 0 then begin @GetMitNavn := GetProcAddress(Handle, 'GetMitNavn'); if @GetMitNavn <> nil then begin Button1.Caption := GetMitNavn(0); end; FreeLibrary(Handle); end; end;
procedure TForm1.Button2Click(Sender: TObject); begin if DLLHandle <> 0 then begin FreeLibrary(DLLHandle); DLLHandle := 0; end; end;
end.
-- slut --
Der kommer ingen fejl... men button1.caption bliver heller ikke "Hejhej" ... der kommer ingen ting ... og ingen fejl ... hvad kan det være ?
Det kunne hjælpe at skrive de rigtige navne: if Handle <> 0 then begin @GetMitNavn := GetProcAddress(Handle, 'GetMitNavn'); Skal ændres til if DLLHandle <> 0 then begin @GetMitNavn := GetProcAddress(Handle, 'MitNavn');
Du skal sørge for at delphimm.dll distribueres sammen med dit program og dLL når du bruger sharemem. Derfor bruger bruger jeg personligt aldrig sharemen, men overfører strenge via PChar typen.
(* * Shared Memory Allocator for Delphi DLL's * Version: 1.2 * * Features: * no runtime dll required. * no performance degradation. * * Usage: * Must be the FIRST UNIT listed in the project file's USES section * for BOTH DLL AND EXE projects. If you install a memory manager for * leak detection, it should be listed immediately after this unit. * * Author: Jens Borrisholt * Thanx to Jesper Hermansen for the idea !!! *)
type TMemMgrPack = record RefCount: Integer; //Reference Count of the MemMgr Signature1: int64; MemMgr: TMemoryManager; Signature2: int64; end; pMemMgrPack = ^TMemMgrPack;
procedure ValidatePack(p: pMemMgrPack); var pid: DWORD; begin // use pid for additional safety; p^.RefCount := 1; pid := GetCurrentProcessId; p^.Signature1 := SignatureBytes1 xor pid; p^.Signature2 := SignatureBytes2 xor pid; end;
function IsPackValid(p: pMemMgrPack): boolean; var pid: DWORD; begin pid := GetCurrentProcessId; Result := (p^.Signature1 = SignatureBytes1 xor pid) and (p^.Signature2 = SignatureBytes2 xor pid); end;
//next, fixed by Aimingoo repeat Requested := SYSTEMINFO.lpMaximumApplicationAddress; Requested := pointer((DWORD(Requested) div $10000) * $10000); // align on start of last full 64k page dec(integer(Requested), iPages * $10000); Requested := pointer((DWORD(Requested) div SYSTEMINFO.dwPageSize) * SYSTEMINFO.dwPageSize); // align on start of last full 64k page Allocated := VirtualAlloc(Requested, SYSTEMINFO.dwPageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
//find a free memory block or a valid MemMgr if (Allocated <> nil) then if (Requested = Allocated) then Break else else if IsPackValid(Requested) then Break;
inc(iPages); until iPages > iPagesBound;
if Allocated <> nil then begin if Requested <> Allocated then begin MessageBox(0, 'Shared Memory Allocator setup failed: Address was relocated.', 'FastShareMem', 0); Halt; end;
GetMemoryManager(Allocated^.MemMgr); ValidatePack(Allocated); end else begin if not IsPackValid(Requested) then begin MessageBox(0, 'Shared Memory Allocator setup failed: Address already reserved.', 'FastShareMem', 0); Halt; end;
// restore MemMgr to Old, only for DLL or other model if Allocated = nil then SetMemoryManager(OldMemMgr) else if Requested^.RefCount > 0 then TerminateProcess(GetCurrentProcess, 0);
(* cleanup *) if Requested^.RefCount = 0 then VirtualFree(Allocated, 0, MEM_DECOMMIT or MEM_RELEASE) end.
jeh ved ikke hvad der sker her ... men jeg vil bare loade en min DLL fil og bruge den...
procedure TForm1.Button1Click(Sender: TObject); var GetMitNavn: Function ( X: Integer ):STRING;
begin DLLHandle := LoadLibrary('Project1dll.dll'); // fejl Delphimm.dll ikke fundet!
if DLLHandle <> 0 then begin @GetMitNavn := GetProcAddress(DLLHandle, 'MitNavn'); if @GetMitNavn <> nil then begin Button1.Caption := GetMitNavn(0); end; FreeLibrary(Handle); end; end;
"{ Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select View-Project 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 DELPHIMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using DELPHIMM.DLL, pass string information using PChar or ShortString parameters. }"
Ang. Sharemem: En EXE og DLL lavet i Delphi har hver sin memory manager der styrer strenge. En string i Delphi er referencecounted og benytter copy-on-write. Dette kræver styring af det hukomelse som strenge benytter. Der opstår så problemer når du vil bruge en string på tværs af EXE og DLL da memory manageren i hvert modul vil forsøge at allokere og frigive det hukommelsesareal. For at få de 2 memory managers til at virke sammen kan man benytte sharemem, herved koordineres deres arbejde. Alternativet som jeg plejer at bruge er at lade være med at bruge String typen i DLL funktioner, der bruger jeg altid PChar i stedet. Det kræver dog lige lidt styring selv, men er ellers nemt nok.
tolderlund >> Det er jeg så udemærket klar over.. Jeg ved hvordan sådan en memmory manager virker. MIT budskab trænger blot ikke helt ind.
Jeg har skrevet en ny unit som er en erstatning for borlands sharemem. Jeg har kaldt den FastShareMem.pas, fordi den er hurtiger end borlandt. Noget endda.
Hvis man bruger min FastShareMem.pas kan man saktens bruge strings, og andere dynamiske data typer, på tværs af DLL og exe. Vel at mærke uden at skulle distribuere en 3. parts dll fil.
FastShareMem skal blot være den første i din uses i både exe og DLL fil så er du i luften. Så slipper du for Pchar og ShortString !
Jens B
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.