Entwickler-Ecke
Dateizugriff - Pointer und Funktionsaufrufe
jackle32 - So 24.05.15 12:00
Titel: Pointer und Funktionsaufrufe
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:
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; p1 := @i; p1^ := p1^ + 1; j := p1^; p2 := @i; Integer(p2^) := i + 1; j := Integer(p2^); end. |
Das hier aber nicht:
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:
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:
Quelltext
1:
| Zugriffsverletzung bei Adresse 00000000006F5EC2 in Modul 'Anwendung.exe'. Lesen von Adresse FFFFFFFFFFFFFFFF. |
Bin schon auf eure Antworten gespannt.
Gruß,
Jack
Moderiert von Narses: Topic aus Sonstiges (Delphi) verschoben am So 24.05.2015 um 22:46
Sinspin - 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 :
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; 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".
jackle32 - 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
GuaAck - 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 - Mo 25.05.15 00:36
Mein Problem dreht sich nicht um den Aufruf von GetProcAddress.
Vielleicht nochmal kurz:
Es geht darum wie ich
Delphi-Quelltext
1: 2:
| @Funktion := FunktionsPointer; Funktion; |
anders und idealerweise kürzer schreiben kann.
(Deklaration der Variablen aus obigen Beispiel Nummer 3)
Gruß,
Jack
Sinspin - Mo 25.05.15 07:44
Oh sorry, da ist mir ein Fehler unterlaufen. Ich habe das mal angepasst.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!