Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Dll Problem (https://www.delphipraxis.net/94299-dll-problem.html)

mr.unbekannt 19. Jun 2007 17:40


Dll Problem
 
Hi @all,

ih habe ein Problem beim laden einer dll. nachfolgend erstmal den quelltext der dll und des projectes:
Delphi-Quellcode:
unit main;

interface

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

type
  Tfmmain = class(TForm)
    PageControl1: TPageControl;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public

    { Public declarations }
  end;
  TShow_DLLForm = procedure; stdcall;

var
  fmmain: Tfmmain;
  Show_DLLForm: TShow_DLLForm;

implementation


{$R *.dfm}

procedure Tfmmain.Button1Click(Sender: TObject);
var
  dllhandle: Thandle;

begin
  dllhandle := 0;
  try
    dllhandle := LoadLibrary('Project1.dll');
    @Show_DLLForm := GetProcAddress(dllhandle,'startdll');
    if @Show_DLLForm <> nil then
      Show_DLLForm;              
  finally
    FreeLibrary(dllhandle);
    showmessage('fertsch');
  end;

end;


end.
Delphi-Quellcode:
library Project1;

{ 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
  sharemem,
  SysUtils,
  Classes,
  dialogs,
  comctrls,
  main in 'main.pas';




{$R *.res}





procedure startdll;
begin
  fmmain.Button1.Caption := 'test';
end;

begin


end.
mein problem ist nun, dass ich die dll lade, aber die procedure Show_DLLForm nil ist und somit nicht ausgeführt wird. wo liegt der fehler? Habe leider bis jetzt keine Erfahrungen mit Dll's

Muetze1 19. Jun 2007 17:58

Re: Dll Problem
 
1. ShareMem in der DPR des Projektes als erste Unit eintragen und nicht in der Formulardatei des Projektes.
2. Überprüfen des LoadLibrary() Rückgabewertes und nicht fest daran glauben, dass es schon klappen wird.
3. Die DLL sollte auch die Funktion exportieren, dies tut sie bisher noch gar nicht. Von daher ist sie auch nicht in der DLL zu finden.

Ich gebe keine Codebeispiele, da alles dazu in der Hilfe zu finden ist.

Apollonius 19. Jun 2007 18:04

Re: Dll Problem
 
Es kann natürlich sein, dass ich mich täusche, aber für mich sieht es irgendwie ungesund aus, dass die Unit Main in der DLL eingebaut ist. Das heißt doch, dass es jetzt im Projekt und in der DLL zwei verschiedene Formulare gibt, und das ist wahrscheinlich nicht, was du erreichen willst.

Luckie 19. Jun 2007 18:20

Re: Dll Problem
 
Das ist nicht nur ungesund, sondern wiedrspricht auch den Prinzipien einer DLL, die eigentlich programmunabhägig Funktionen bereitstellen sollte.

mr.unbekannt 19. Jun 2007 18:24

Re: Dll Problem
 
wie funktioniert diese exportfunktion in diesem beispiel? die dll findet er.

Apollonius 19. Jun 2007 18:26

Re: Dll Problem
 
Vor begin...end. gibt es einen Exports-Abschnitt. Ich verlinke hier einfach mal auf dsdt, da wird es erklärt.

nitschchedu 19. Jun 2007 18:29

Re: Dll Problem
 
1. Du kannst in der Dll nicht auf was zugreifen was er nicht kennt !!!
2. Lass ja diese ShareMem Unit weg die ist sinloss !!!

Ich kann dir ne Beispiel machen wenn du willst wie das geht ;-)

Luckie 19. Jun 2007 18:36

Re: Dll Problem
 
Zitat:

Zitat von nitschchedu
2. Lass ja diese ShareMem Unit weg die ist sinloss !!!

Kannst du diese Aussage auch begründen?

nitschchedu 19. Jun 2007 18:45

Re: Dll Problem
 
Natürlich ;-) also wenn ich die Unit einbinde kann ich String übergeben (Tolle sache), wenn ich dabei berücksichtige das die DLL um einige Byts größer würd.
Das geht viel leichter in dem ich PChar nehme gibts null Probleme.

Ich mache hier gleich mal das Bsp:

DLL :
Delphi-Quellcode:
library Project1;

uses
  SysUtils,
  Classes,
  dialogs,
  comctrls;




{$R *.res} 





function startdll: PChar;
var
 Test: String;
begin
  Test := 'test';
  Result := PChar(Test);
end;

begin

exports
 startdll;

end.
So und nun das Programm:

Delphi-Quellcode:
type
 TTest = function: PChar;

procedure Tfmmain.Button1Click(Sender: TObject);
var
  dllhandle: Thandle;
  myFunc: TTest;
begin
  dllhandle := 0;
  try
    dllhandle := LoadLibrary('Project1.dll');
    @myFunc := GetProcAddress(dllhandle,'startdll');
    if @myFunc <> nil then
      form1.edit.text := myFunc;
  finally
    FreeLibrary(dllhandle);
    showmessage('fertsch');
  end;

end;
So habs jetzt aber noch nicht getestet ;-)

Muetze1 20. Jun 2007 23:48

Re: Dll Problem
 
Zitat:

Zitat von nitschchedu
Das geht viel leichter in dem ich PChar nehme gibts null Probleme.

Das gibt bei einem solchen kleinen Prog wohl keine Probleme, aber trotzdem ist das Beispiel murks. Du gibst als Result einen PChar zurück. Diesen erhälst du aus einer temporären Umwandlung eines Strings. Der String wiederrum ist eine lokale Variable und verliert somit ihre Gültigkeit mit verlassen der Procedure. Damit wird mit dem Rücksprung aus deiner DLL Procedure der String "test" ungültig und damit die von der temporären Umwandlung erzeugte PChar. Das der PChar vllt. noch richtig im Hauptprogramm ausgegeben wird bedeutet einfach nur, dass der Speicher wo die Daten des Strings "test" lagen noch nicht wieder erneut verwendet wurden. Das ist aber ein Spiel mit dem Feuer - da empfehle ich dir lieber Lotto, da sind die Gewinnchancen nicht so hoch, aber man hat bei einem Gewinn länger was davon als von dem Result deiner Funktion.

Der Code ist ein sehr gutes Beispiel wie man es nicht macht.

Frage dazu an dich, nitschchedu: Wenn dies so einfach ist, warum gibt es keine WinAPI Funktion welche einen PChar zurück gibt sondern alle wollen einen Buffer und dessen Grösse haben, den sie dann vollschreiben.

Grundlegend könntest du deinen Code auch schnell und simpel richtig gestalten: Deklariere die Variable "test" global in der DLL (somit verliert sie ihre Gültigkeit erst mit entladen der DLL).

EDIT: Ein Tutorial dazu welches alles nötige erklärt und aufzeigt wie man es machen könnte: Luckie's DLL String Artikel


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:21 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz