Hallo himitsu,
Zitat von
himitsu:
Delphi ist dafür leider nicht ausgelegt
Schade. Hast Du eine verlässliche Quelle für diese Aussage, oder ist das die Essenz aus Deinen Bemühungen?
Delphi hat in der Tat auch andere Probleme mit Adressen im Zusammenhang mit dem @-Parameter
Delphi-Quellcode:
procedure TestProc(param: string); overload;
procedure TestProc(param: Integer); overload;
type
TStringProc = procedure(param: string);
TIntProc = procedure(param: Integer);
wenn Du nun eine Zuweisung der Art
Delphi-Quellcode:
var
myStringProc: TStringProc;
myIntProc: TIntProc;
begin
myStringProc := @TestProc;
myIntProc := @TestProc;
Assert( Pointer(myIntProc)=Pointer(myStringProc) );
durchführst, weist der Compiler
myIntProc dieselbe Variable zu, wie es bei Deinem
Call wäre: Immer die erste.
Abhilfe schafft die Zuweisung ohne Operator
Delphi-Quellcode:
myStringProc := TestProc;
myIntProc := TestProc;
Assert( Pointer(myIntProc)<>Pointer(myStringProc) );
Dein Problem wird beim Einsatz mit DLLs (zB bei BPLs) mithilfe von gesonderten Exportnamen (name manging) gelöst, was im Wesentlichen einem Vergeben eines Alias entspricht. Ohne nun die Routinen zunächst in eine
BPL verschieben zu müssen, könntest Du einen solchen Alias über Konstanten realisieren:
Delphi-Quellcode:
const
STRING_PROC : TStringProc = TestProc;
INT_PROC: TIntPRoc = TestProc;
diese Zuweisung kann auch lokal, also in Deiner Routine geschehen, in der Du die Assembleraufrufe gestalten möchtest. Problematisch an diesem Ansatz ist leider die interne Realisierung typisierten Konstanten. Sie entsprechen in Delphi einer Art "globaler Variablen". Aus diesem Grund steht
INT_PROC nun nicht für eine Adresse,
Code:
MOV EAX, $1234
CALL INT_PROC ; ? FEHLER ? Nein, siehe Erklärung
sondern einer globalen Pointer-Variable. Sie muss dann entsprechend beim Aufruf dereferenziert werden. Glücklicherweise übernimmt der Compiler das für uns, so dass folgendes funktioniert:
Code:
MOV EAX, $1234
CALL INT_PROC ; = CALL [INT_PROC]
Dies ist leider ein kleiner Performancevelust, erspart Dir aber die Änderung des bestehenden überladenen Codes oder das Einführen von Wrapper-Routinen.
Eine Assemblerroutine, die die Integervariante der überladenen Variante von
TestProc aufruft könnte demnach ohne neue Symbole nach außen zu veröffentlichen oder Anforderungen an den aufzurufenen Code zu stellen (allerdings auf Kosten einer impliziten Dereferenzierung) so aussehen:
Delphi-Quellcode:
procedure AssemberCallsIntegerVersion;
assembler;
const
TestProc_Integer:
procedure(Param: Integer) = TestProc;
asm
MOV EAX, $1234
CALL TestProc_Integer
end;
Ich hoffe das hilft... Und würde Dich bitten, die Frage weiterhin als "offen" zu lassen. Mich würde eine direkte Variante ebenfalls interessieren