Autor Beitrag
jackle32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: So 24.05.15 12:00 
Hallo zusammen,

ich bin gerade dabei mich in Dll´s und alles was damit zusammenhängt einzuarbeiten.

Dabei bin ich auf die Möglichkeit gestoßen, DLL´s dynamisch einzubinden.

Dabei habe ich gesehen, dass es den klassischen Weg gibt in dem ich die Funktion im "Type" abschnitt vordefiniere, mir eine Variable davon anlege und mittels @Variable und GetProcAddress die Adresse aus der Dll hole.

In einem anderem Programm habe ich gesehen, dass das Ergebnis von GetProcAddress direkt auf eine Variable vom Typ TFarProc übergeben wird. Nach etwas nachlesen in den Units bin ich drauf gekommen, dass es sich dabei ja eigentlich um einen ganz normalen Pointer handelt. (Hoffe des stimmt soweit)

Jetzt zu meiner Frage.

Warum geht so etwas (Beispiel aus einem Forum), speziell der markierte Bereich sollte analog meinen unteren Beispiel sein:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var
  i, j: Integer;
  p1: ^Integer;
  p2: Pointer;
begin
  i := 1;
 
  { typisiert }
 
  p1 := @i;       // dem Zeiger wird die Adresse der Integer-Variable übergeben
  p1^ := p1^ + 1// hier wird der Wert um eins erhöht
  j := p1^;       // typisiert: der Variable j wird 2 übergeben
 
  { untypisiert }
 
  p2 := @i;       // analog oben
  Integer(p2^) := i + 1;
  j := Integer(p2^);
end.


Das hier aber nicht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type

  TFNFunktion = procedure (); stdcall;

var
  FunktionsPointer: TFarProc = Nil;

procedure DllEinlesen()
var
  DllHandle: THandle;
begin
  DllHandle := LoadLibrary('DllName');

  FunktionsPointer := GetProcAddress(DllHandle, 'Funktionsname');
end;

procedure TForm1.Button1Click(Sender: TObject)
begin
  TFNFunktion(FunktionsPointer^);
end;


Ich für mein Verständnis würde sagen es müsste gehen, tut es aber nicht. Vom Mechanismus her müsste des doch sein, schau auf die Adresse und mache abhängig von dem Typ das was an der Adresse steht.

Was schon geht um alle zu erklären was ich getestet habe ist:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
type

  TFNFunktion = procedure (); stdcall;

var
  FunktionsPointer: TFarProc = Nil;
  Funktion: TFNFunktion = Nil;

procedure DllEinlesen()
var
  DllHandle: THandle;
begin
  DllHandle := LoadLibrary('DllName');

  FunktionsPointer := GetProcAddress(DllHandle, 'Funktionsname');
end;

procedure TForm1.Button1Click(Sender: TObject)
begin
  @Funktion := FunktionsPointer;
  Funktion;
end;


(Ich habe meine Beispiele frei runter geschrieben, da mein Programm noch umfangreicher ist und daraus wahrscheinlich nicht klar geworden wäre auf was ich hinaus will. Daher ist es gut möglich, dass ein Rechtschreib- oder Formellerfehler drin ist. Darum geht es mir auch nicht, sondern nur um das Verhalten von Pointer bei Funktionsaufrufen.)

Ach so der Fehler den ich bekomme wenn ich das mittlere Beispiel versuche ist:

ausblenden Quelltext
1:
Zugriffsverletzung bei Adresse 00000000006F5EC2 in Modul 'Anwendung.exe'. Lesen von Adresse FFFFFFFFFFFFFFFF.					


Bin schon auf eure Antworten gespannt.

Gruß,
Jack


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am So 24.05.2015 um 22:46

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1175
Erhaltene Danke: 94

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: So 24.05.15 13:05 
1. Du brauchst das Dll Handle noch um die Dll später wieder entladen zu können. Daher ist es ziemlich unklug dieses in der procedure zu deklarieren.
2. Dein mittleres Beispiel... :gruebel:
3. Probier mal das :

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
type
  TFNFunktion = procedure (); stdcall// beim festlegen des Typs beachten welche Parameter die Procedure hat

var
  DllHandle: THandle;
  Funktion: TFNFunktion = Nil;

procedure DllLaden();
begin
  DllHandle := LoadLibrary('DllName');
  if DllHandle <> 0 then
  begin
    Funktion := GetProcAddress(DllHandle, 'Funktionsname');
  end;
end;

procedure DllEntladen;
begin
  if DllHandle <> 0 then
    FreeLibrary(DllHandle);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  DllLaden;
  try
    if Assigned(Funktion) then
      Funktion;
  finally
    DllEntladen;
  end;
end;


Mir ist klar das in dem Beispiel so ziemlich die ganze Fehlerauswertung fehlt, aber zum rumspielen reicht das erstmal.

€: Falschen Bezeichner entfernt, "FunctionPointer" ersetzt durch "Funktion".

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.


Zuletzt bearbeitet von Sinspin am Mo 25.05.15 07:46, insgesamt 2-mal bearbeitet
jackle32 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: So 24.05.15 18:13 
Hallo Sinspin,

danke für deine Antwort.

zu 1.: Ja ich weiß, wie gesagt war ja auch kein reales Beispiel und sollte nicht zum nachmachen aufrufen... :wink:

zu 2.: im zweiten Beispiel mache ich eigentlich das gleiche wie im Ersten mit Integern gemacht wird nur eben mit Funktionen, aber leider mit beschriebenen Problemen.

zu 3.: Sieht auf den ersten Blick ja nach dem "normalen" Weg aus. Eine kleine Frage: Wie und wo definierst du "FunktionsPointer"?

Und grundsätzlich, natürlich ist auch in meinen original Code noch einiges an Fehlerbehandlung außen rum. Das habe ich aber mit Absicht weg gelassen um meine eigentliche Frage nicht zu sehr zu verstecken.

Gruß,
Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
GuaAck
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 303
Erhaltene Danke: 29

Windows 8.1
Delphi 7 Pers.
BeitragVerfasst: So 24.05.15 22:58 
Hallo jackle32,

mit Strings habe ich in diesem Zusammenhang gelegentlich Probleme gehabt.

mit

var
name: string;

geht es mit der expliziten Umwandlung:

p := GetProcAddress(dllHandle, pansichar(name));

Probieren,
Gruß Gueack
jackle32 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Mo 25.05.15 00:36 
Mein Problem dreht sich nicht um den Aufruf von GetProcAddress.

Vielleicht nochmal kurz:

Es geht darum wie ich

ausblenden Delphi-Quelltext
1:
2:
@Funktion := FunktionsPointer;
Funktion;

anders und idealerweise kürzer schreiben kann.

(Deklaration der Variablen aus obigen Beispiel Nummer 3)


Gruß,
Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1175
Erhaltene Danke: 94

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: Mo 25.05.15 07:44 
Oh sorry, da ist mir ein Fehler unterlaufen. Ich habe das mal angepasst.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.