Konwencje wywołania

moRs

Wstęp

Konwencje wywołania określają zależności między procedurą/funkcją a ich wywołującym. Są to:

  • kolejność przekazywania parametrów do procedury/funkcji przez wywołującego,
  • przypisanie pracy usuwania parametrów ze stosu (czyszczenia, balansowania stosu) po zakończeniu pracy wywołującemu lub wywoływanemu,
  • użycie rejestrów przy przekazywaniu parametrów,
  • obsługa błędów i wyjątków.

W Delphi wyróżniamy następujące konwencje wywołania:

  • register,
  • stdcall,
  • safecall,
  • cdecl,
  • pascal.

Konwencje wywołania są wybierane przy deklaracji procedury/funkcji poprzez dodanie dyrektywy kompilatora o takiej samej nazwie jak konwencje, na przykład:

function Foo( var X: Integer; const C: Byte ): Boolean; cdecl; //przy wywołaniu funkcji Foo zostanie użyta konwencja cdecl

W konwencjach register i pascal parametry przekazywane są do procedury/funkcji od lewej do prawej, tj. pierwszym obliczanym i przekazywanym parametrem jest ten najbardziej po lewej, ostatnim najbardziej po prawej. W konwencjach cdecl, safecall i stdcall parametry są przekazywane od prawej do lewej.

Informacje

W wszystkich konwencjach oprócz cdecl, wywołana procedura lub funkcja usuwa parametry ze stosu zanim zwróci kontrolę wywołującemu. W konwencji cdecl wywołujący musi usunąć parametry ze stosu po zakończeniu działania procedury/funkcji.

W konwencji register do przekazywania parametrów użyte zostają maksimum trzy rejestry procesora, w pozostałych konwencjach do przekazywania parametrów używa się tylko stosu.

Konwencja safecall implementuje "firewalle" wyjątków. W Windows, jest to implementacja informowania o błędach COM między procesami.

Poniższa tabela podsumowuje konwencje wywołania:

KonwencjaKolejność parametrówSprzątaniePrzesyłanie parametrów przez rejestry
registerod lewej do prawejprocedura/funkcjaTak
pascalod lewej do prawejprocedura/funkcjaNie
cdeclod prawej do lewejwywołującyNie
stdcallod prawej do lewejprocedura/funkcjaNie
safecallod prawej do lewejprocedura/funkcjaNie

Konwencja register jest najefektywniejsza, gdyż zazwyczaj unika się przy niej tworzenia ramki stosu. Konwencja cdecl jest użyteczna gdy wywołujesz funkcje bibliotek napisanych C/C++ lub C++, podczas gdy konwencje stdcall i safecall są rekomendowane do wywołań do kodu zewnętrzenego. W API Win32 używane są konwencje stdcall i safecall. Inne systemy operacyjne ogólnie używają cdecl. (Uwaga: stdcall jest efektywniejsze od cdecl.)

Metody dostępowe do właściwości Published klas muszą używać konwencji register.

Konwencja safecall musi być używana do deklarowania metod interfejsów dualnych.

Konwencja pascal jest zachowywana dla wstecznej zgodności. Dyrektywy związane z konwencjami wywołania - near, far i export - odnoszą się do konwencji używanych w 16-bit Windowsie. Nie mają one efektu w 32-bitowych aplikacjach i są zachowywane tylko dla wstecznej zgodności.

Szczegóły

Konwencja register

Konwencja register (w języku C/C++ i pochodnych fastcall) domyślnie używana jest w kompilatorach Delphi począwszy od wersji 2. Pierwsze trzy parametry, dla których jest to możliwe, przekazywane są przez rejestry EAX, EDX i ECX, reszta paramtrów przekazywana jest przez stos. W konwencji register do nazwy procedury/funkcji kompilator dodaje na początek znak '@'.

Konwencja cdecl

Konwencja cdecl jest domyślną konwencją w programach pisanych w C/C++ i C++. Dzięki temu, że parametry przekazywane są od prawej do lewej możliwa jest implementacja funkcji z zmienną ilością parametrów.

Konwencja stdcall

Konwencja stdcall jest domyślnie używana przez API Windows. Jeżeli chcesz by Twoje biblioteki DLL pisane w Delphi były zgodne z innymi programami napisanymi pod Windows używaj dla eksportowanych procedur i funkcji tej konwencji.

Konwencja safecall

W Delphi konwencja safecall obejmuje obsługę błędów COM (Component Object Model), dzięki czemu wyjątki nie są przepuszczane do wywołującego, ale raportowane w wartości zwrotnej HRESULT, zgodnie z wymaganiami COM/OLE. Delphi automatycznie sprawdza zwracaną wartość HRESULT i wywołuje wyjątek jeśli trzeba.

Konwencja pascal

Konwencja pascal była domyślnie używana w Delphi 1. Jest odwrotnością konwencji wywołania C/C++ - cdecl. Jest ona dziedzictwem programowania 16-bitowego, gdzie używano ją domyślnie, w programowaniu 32-bitowym już nie jest używana.

Zobacz też:

2 komentarzy

Bardzo ładnie i czytelnie napisany art.
Tu jest literówka, ale to jakoś tak nie po polskiemu w ogóle chyba.. niezrozumiałe nieco.
"ale raportowane w wartności zwracaną HRESULT"