Avatar billede dl Nybegynder
15. august 2003 - 13:17 Der 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;

EXPORTS
  Mitnavn;

begin
end.

-- slut --



så har jeg en app. med denne kode

-- start --

unit Unit1;

interface

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

type

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    DLLHandle: THandle;

  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

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 ?
Avatar billede borrisholt Novice
15. august 2003 - 13:20 #1
Du har glemt ShareMem.pas

Læs den text det står i starten af din DLL fil :-)
Avatar billede borrisholt Novice
15. august 2003 - 13:20 #2
uses
  ShareMem,
  SysUtils,
  Classes;
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:22 #3
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');
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:24 #4
Det skal selvfølgelige være
  @GetMitNavn := GetProcAddress(DLLHandle, 'MitNavn');
Avatar billede borrisholt Novice
15. august 2003 - 14:26 #5
Rentfaktisk skal du bruge BEGGE svar.

Jens B
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:27 #6
I øvrigt kan du slette EXPORT fra
Function Mitnavn( X: Integer ): STRING; EXPORT
i dit DLL, den har ingen betydning i 32bit applikationer.
Avatar billede dl Nybegynder
15. august 2003 - 14:30 #7
k, nu har jeg rettet de ting ... og nu får jeg en fejl: delphimm.dll blev ikke fundet.
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:35 #8
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.
Avatar billede borrisholt Novice
15. august 2003 - 14:37 #9
Personligt bruger jeg min egen Sharemem

unit FastShareMem;

(*
* 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 !!!
*)

interface

implementation
uses Windows, SysUtils;

const
  SignatureBytes1 = $BABE01234567FEED;
  SignatureBytes2 = $F00D76543210B00B;
  iPagesBound = 15;

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;

var
  SYSTEMINFO : TSYSTEMINFO;
  OldMemMgr: TMemoryManager;
  Requested, Allocated: pMemMgrPack;
  iPages: integer;

initialization
  GetSystemInfo(SYSTEMINFO);
  iPages := 0;

  //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;

    GetMemoryManager(OldMemMgr);
    SetMemoryManager(Requested^.MemMgr);
    inc(Requested^.RefCount);
  end;

finalization
  // fix Reference Count
  dec(Requested^.RefCount);

  // 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.



Jens B
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:38 #10
Hm, jeg synes det er nemmere at lade være med at bruge sharemem eller andre ekstra ting. Det er selvfølgelig smag og behag.
Avatar billede borrisholt Novice
15. august 2003 - 14:43 #11
Det kan man selvfølgelig sige. Men min unit skal du ikke distribuere nogen extern dll fil
Avatar billede dl Nybegynder
15. august 2003 - 14:43 #12
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;
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:46 #13
Som sagt, delphimm.dll skal være til stede når du bruger sharemem.
I øvrigt:
  FreeLibrary(Handle);
skal være
  FreeLibrary(DLLHandle);
Avatar billede borrisholt Novice
15. august 2003 - 14:48 #14
tolderlund >> Ja hvis du bruger sharedmem, men ikke hvis du bruger min unit...

Jens B
Avatar billede dl Nybegynder
15. august 2003 - 14:49 #15
tolderlund>> fik det til at virke med dine point ... og unden sharemem

Men hvad gør sharemen ..??
Avatar billede borrisholt Novice
15. august 2003 - 14:50 #16
Læd den kommentar der står i starten af dit SPM.
Avatar billede athlon-pascal Juniormester
15. august 2003 - 14:51 #17
"{ 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. }"
Avatar billede dl Nybegynder
15. august 2003 - 14:52 #18
hmm ... min fejl... takker ...
Avatar billede tolderlund Nybegynder
15. august 2003 - 14:58 #19
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.
Avatar billede borrisholt Novice
16. august 2003 - 14:01 #20
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
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