Entwickler-Ecke

Dateizugriff - DLL GetProcAddress


thepaine91 - Do 22.10.09 15:03
Titel: DLL GetProcAddress
Hi ich hatte grad ein Problem das ich zwar schon gelöst habe mir stellt sich jetzt allerdings folgende Frage:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
type   
  TAddierenProc = function(a, b: integer): integer; stdcall

type Tform1 = class(Tform)
  ...
  public
    FarProc: TAddierenProc;  // Variante 1

...
var 
  Form1 := Tform1;
  FarProc: TAddierenProc;  // Variante 2

  begin
    FarProc := GetProcAddress(lib, 'Addieren');  // Fehlerquelle für Variante 1
    if Assigned(FarProc) then
      i :=  FarProc(12);  // Fehler wird ausgelöst bei Variante 1


Weis jemand warum Variante 1 nur mit folgendem aufgerufen werden kann?

Delphi-Quelltext
1:
  @Farproc := @FarProc := GetProcAddress(lib, 'Addieren');  // sonst Fehler bei lesen von Adresse....                    


Und Variante 2 mit "@Farproc := .." & ohne @ also "Farproc := .."

Hoffe mir kann jemand Helfen dieses "Mysterium" zu lösen. :P

mfg nic


Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Do 22.10.2009 um 16:25


HelgeLange - Do 22.10.09 15:55

Dein TFarProc ist ein leerer Funktionszeiger.
GetProcAdress liefert einen Funktionszeiger.
@liefert die Adresse von etwas.
@Farproc liefert die adresse im Speicher, wo die leeren 4 Byte des Funktionszeigers sind.
@Farproc := GetProcAdress(lib, 'MyDLLProc'); speichert die von GetProcAdress erhaltene Adresse im Speicher von FarProc.
FarProc ohne @ ruft die funktion selbst auf. Hast Du vorher nichts drin gespeichert, ist sie nil oder hat müll drin, beide fälle führen zu einem Fehler. Immer schön mit Assigned prüfen nach dem GetProcAdress.


thepaine91 - Do 22.10.09 16:17

Ich glaube meine Frage ist missverstanden worden.

Variante 1 läuft auch durchs Assigned knallt aber trotzdem bei

Delphi-Quelltext
1:
  i :=  FarProc(12);  // Fehler wird ausgelöst bei Variante 1 / Variante 2 funktioniert trotzdem                    


Wenn ich aber Variante 2 nutze funktioniert es mit dem selben Aufruf...
Zudem hab ich im Debuger mal Farproc ausgewertet und die Adresse hatte gestimmt

Frage woran liegt das?


uall@ogc - Do 22.10.09 16:58

Wie wird die Funktin TAddierenProc in der DLL exportiert? Außerdem zeigst du uns nocht den originalen Code, deiner einige Fehler enhält.
Ich denke mal eher, dass deine Definition von Addieren falsch ist.


thepaine91 - Do 22.10.09 17:46

Wenn die Definition von Addieren falsch wäre würden Variante 1 und 2 auch nicht funktionieren?
Ich will nur wissen warum Variante 1 nur mit @FarProc und Variante 2 auch ohne @ funktioniert.
Mehr nicht.


HelgeLange - Do 22.10.09 17:59

liegt vielleicht daran, wie der Delphi-Compiler die variablen verwaltet, variante 1 ist ja ein Mitglied eines Objektes, also ein 8-byte-Pointer. variante 2 scheint mir eine stack variable zu sein (nur für die procedure), kann man aber schlecht sagen, da Du ja nicht den ganzen source postest, der relevant wäre.


Flamefire - Do 22.10.09 22:55

das problem ist, das in variante 1 die funktion eine objekt funktion ist
-->das objekt wird als parameter mitgegeben (versteckt)
-->falscher parameter-->unerwarteter wert-->fehler

Lösung: funktion gloabl oder lokal machen


Xentar - Do 22.10.09 23:44

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
das problem ist, das in variante 1 die funktion eine objekt funktion ist
-->das objekt wird als parameter mitgegeben (versteckt)
-->falscher parameter-->unerwarteter wert-->fehler

Lösung: funktion gloabl oder lokal machen

Hm? Dass das bei Methoden (Prozeduren / Funktionen) so ist, war mir ja bekannt. Aber die Funktion ist in diesem Fall eine "Variable" vom Typ TAddierenProc, und da steht kein of object hinter?


thepaine91 - Do 22.10.09 23:45

Hm k mich hat einfach nur mal der Hintergrund interessiert. Mit einem @ davor klappt es ja wunderbar. ;)
Auch in allen Quellen von Borland setzen sie überall das @ daher wird das wohl die bessere Variante sein.

Aber vil kennt jemand ja sicher den Grund für das Verhalten. Wenn nicht auch gut auf jeden fall Danke für eure bemühungen....


HelgeLange - Fr 23.10.09 05:20

OK, um das klar zu stellen im Functionszeiger-Unterschied : Delphi unterscheidet zwischen einer Funktion in einem Objekt und einer "normalen" Funktion


Delphi-Quelltext
1:
2:
Type TMyObjectProc = procedure(nParam: Integer) of Object;
     TMySimpleProc = procedure(nParam: Integer);


Dieses sind unterschiedliche Deklarationen, weil der 1 einen 8-Byte-Zeiger erzeugt (wie flamefire schon sagte : versteckt!) und die zweite erzeugt nur einen 4-Byte-Zeiger.

Deswegen gilt dann :


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
Type MyClass = class
     private
       procedure __MyObjectProc(nParam: Integer);
     end;

procedure __MySimpleProc(nParam: Integer);

implementation

var aMyObjectProc : TMyObjectProc;
    aMySimpleProc : TMySimpleProc;
    aMyClass : TMyClass;

begin
  @aMyObjectProc := @aMyClass.__MyObjectProc;  // <-- RICHTIG
  @aMySimpleProc := @aMyClass.__MyObjectProc;  // <-- FALSCH

  @aMyObjectProc := @MySimpleProc;  // <-- FALSCH
  @aMySimpleProc := @MySimpleProc;  // <-- RICHTIG
end;


es müssten natürlich noch die proceduren geschrieben werden und das TMyClass objekt erzeugt, ich habe darauf mal verzichtet...


thepaine91 - Fr 23.10.09 09:09

Okay Danke ;) dann weis ich jetzt wenigstens warum das so ist. ;)


Flamefire - Fr 23.10.09 13:31

ok und der unterschied zwischen den 2 varianten wahr wohl die zuweisung? also:

Delphi-Quelltext
1:
2:
@FarProc := GetProcAddress(lib, 'Addieren');
FarProc := GetProcAddress(lib, 'Addieren');


dann war der fehler, dass der erste fall den zeiger auf die adresse umschreibt, und der 2. fall (vermutlich) irgendwas mit dem funktionsergebnis versucht zu machen, das natürlich nicht geht
warum es bei einer lokalen variable funktioniert, ist mir nicht bekannt...macht vermutlich der compiler
im normalfall muss das @ verwendet werden