Eksperymentuję z możliwością dynamicznego wywoływania procedur lub funkcji znajdujących się w tabeli funkcji. Konkretną aplikacją jest biblioteka DLL, która eksportuje wskaźnik do tabeli funkcji wraz z informacją o liczbie argumentów i typów. Aplikacja hosta ma następnie możliwość przesłuchania biblioteki DLL i wywołania funkcji. Gdyby były to metody obiektowe, mógłbym użyć Rtti do ich wywołania, ale są to normalne procedury i funkcje. DLL musi eksportować normalnych wskaźników funkcji obiektów, ponieważ nie DLL można zapisać w dowolnym języku, w tym C, Delphi itpJak dynamicznie wywoływać nazwaną procedurę lub funkcję w Delphi
Na przykład, mam rekord zadeklarowane i wypełnione w DLL:
TAPI = record
add : function (var a, b : double) : double;
mult : function (var a, b : double) : double;
end;
PAPI = ^TAPI;
odzyskać wskaźnik do tego rekordu, zadeklarowane jako:
apiPtr : PAPI;
Przyjmijmy również mieć dostęp do nazw procedur, liczba argumentów i typów argumentów dla każdego wpisu w rejestrze.
Załóżmy, że chcę wywołać funkcję dodawania. Wskaźnik funkcji, aby dodać będą:
@apiPtr^.add // I assume this will give me a pointer to the add function
Zakładam, nie ma innej drogi inne niż korzystać z niektórych asm naciskać niezbędnych argumentów na stosie i pobrać wynik?
Pierwsze pytanie, jaka jest najlepsza konwencja wywołująca, aby zadeklarować procedurę jako cdecl? Najłatwiej jest złożyć stos przed połączeniem.
Drugie pytanie, czy istnieją przykłady online, które faktycznie to robią? Natknąłem http://www.swissdelphicenter.ch/torry/showcode.php?id=1745 (DynamicDllCall), który jest zbliżony do tego, co chcę, ale uproszczone, jak poniżej, to teraz zwraca wskaźnik (EAX) w wyniku:
function DynamicDllCall(proc : pointer; const Parameters: array of Pointer): pointer;
var x, n: Integer;
p: Pointer;
begin
n := High(Parameters);
if n > -1 then begin
x := n;
repeat
p := Parameters[x];
asm
PUSH p
end;
Dec(x);
until x = -1;
end;
asm
CALL proc
MOV p, EAX <- must be changed to "FST result" if return value is double
end;
result := p;
końcowego;
ale nie mogę go uruchomić, zwraca wartość dla pierwszych parametrów zamiast wyniku. Może mam błędną konwencję wywoływania lub może nie rozumiem, jak odzyskać wynik w EAX.
Wzywam DynamicDllCall następująco:
var proc : pointer;
parameters: array of Pointer;
x, y, z : double;
p : pointer;
begin
x:= 2.3; y := 6.7;
SetLength(parameters, 2);
parameters[0] := @x; parameters[1] := @y;
proc := @apiPtr^.add;
p := DynamicDllCall(proc, Parameters);
z := double (p^);
Wszelkie porady wdzięcznością odbierane. Rozumiem, że niektórzy mogą czuć, że nie jest to sposób, w jaki należy to robić, ale nadal jestem ciekawy, czy jest to co najmniej możliwe.
Aktualizacja 1 Mogę potwierdzić, że funkcja dodawania otrzymuje prawidłowe wartości do dodania.
Aktualizacja 2 Jeśli zmienię podpis dodać do:
add : function (var a, b, c : double) : double;
i przypisać wynik do c wewnątrz dodać, to mogę odzyskać prawidłową odpowiedź w tablicy parametrów (zakładając, że dodasz więcej elementu, 3 zamiast 2). Problem polega na tym, że źle rozumiem sposób zwracania wartości z funkcji. Czy ktoś może wyjaśnić, w jaki sposób funkcje zwracają wartości i jak je odzyskać?
Aktualizacja 3 Mam swoją odpowiedź. Powinienem się domyślić. Delphi zwraca różne typy za pośrednictwem różnych rejestrów. np. całkowite zwrócenie przez EAX, podwójne z drugiej strony zwraca przez ST (0). Aby skopiować ST (0) do zmiennej wyniku, muszę użyć "FST result" zamiast "MOV p, EAX". Teraz przynajmniej wiem, że w zasadzie można to zrobić. Niezależnie od tego, czy jest to sensowne, to inna sprawa, o której muszę teraz myśleć.
To było miłe wprowadzenie do Delphi ASM na stronie www.delphi3000.com (articles/article_3766.asp), ale ta strona już nie istnieje ... –
Być może dokumentacja w [Procedurach montażu i funkcjach] (http : //docwiki.embarcadero.com/RADStudio/XE4/en/Assembly_Procedures_and_Functions) pomogłoby. Zobacz temat "Wyniki funkcji". –
Nie ma zbyt wiele i oficjalni doktorzy nie są strasznie przydatni.Jednak zebrałem wystarczającą ilość informacji od: http://stackoverflow.com/questions/15786404/fld-instruction-x64-bit i http://www.guidogybels.eu/docs/Using%20Assembler%20in% 20Delphi.pdf – rhody