2015-08-15 13 views
9

Muszę zadzwonić non-statycznych C++ funkcje składoweDelphi thiscall wywołanie konwencja

Stąd muszę użyć thiscall wzywającą Konwencję.

Delphi nie obsługuje tej konwencji wywoływania.

Więc zanim mogę zadzwonić do którejkolwiek z funkcji członka, muszę ręcznie popchnąć parametry w stosie.

asm 
    mov ecx, myClassPointer 
    end; 

To działa dobrze, ale szukam lepszego sposobu na zrobienie tego.

W tej chwili wywołuję kod asm za każdym razem z classpointer przed wywołaniem funkcji, co nie jest miłe.

Ponieważ nie jestem ekspertem od Delphi, zastanawiam się, czy można zadeklarować własną konwencję wywoływania lub zautomatyzować wywoływanie tych wszystkich metod klasy.

+2

Napisałem kilka [tego typu adapterów do bogatych w edycję Microsoft interfejsów] (http://www.cs.wisc.edu/~rkennedy/windowless-rtf), które niepoprawnie pominęły konwencje wywołujące. Moje adaptery owijają interfejsy w obu kierunkach, więc kod Delphi może wywoływać kod Microsoftu, a kod Microsoftu może oddzwaniać do interfejsu Delphi, a każda ze stron myśli, że druga dostarcza oczekiwaną konwencję wywoływania. Może okaże się to przydatne. –

Odpowiedz

4

Konwencja wywoływania Delphi register używa rejestrów dla pierwszych trzech parametrów. Pierwsze dwa to EAX i EDX, które są nieużywane w konwencji wywoływania thiscall i można je ustawić na dowolne.Trzeci z tych rejestrów to ECX.

przekazuje wszystkie argumenty na stosie, a register przekazuje pozostałe argumenty na stosie. Zarówno register, jak i thiscall mają argumenty czyszczenia czyszczącego przekazywane na stosie.

Możesz więc zadeklarować funkcję register z parametrami atrapa dla EAX i EDX. Nadal można zawinąć to w inną funkcję, aby ułatwić wywoływanie, ale przynajmniej teraz ta funkcja opakowania może zostać zadeklarowana jako inline.

Pamiętaj jednak, że kolejność, w jakiej argumenty są przekazywane na stosie, różni się między thiscall i register, więc musisz odwrócić parametry, aby dopasować.

5

Dostępne są następujące opcje: Adaptery

  • napisać w asm do wywołania funkcji. To jest twoje obecne rozwiązanie, a jak wiesz, podejście jest kruche i niezręczne.
  • Napisz adapter C++, który przedstawia interfejs przyjazny dla interopera.

Ta ostatnia opcja jest, moim zdaniem, właściwym rozwiązaniem. Kod C++ nie nadaje się do współdziałania. Ujawnianie klas C++ poprzez interop jest po prostu błędne. Nakłada nieuzasadnione wymagania na konsumenta. Rozsądne podejścia obejmują COM i zwykły interop w stylu C, jak w Win32.

Napisz adaptacyjną bibliotekę DLL w C++, która pochłania nierozsądne klasy C++ i udostępnia odpowiedni przyjazny interfejs. Adapter jest napisany w C++ i dlatego jest w stanie zużywać kod C++. Ale potem eksportuje przyjazny interfejs między interfejsami, który można łatwo wywołać z dowolnego łańcucha narzędzi.

+0

Proszę o szczegóły dotyczące części adapterów. Nigdy nie słyszałem o tym w terminach wywoływania funkcji delphi. Zasadniczo powinien wywołać kod asm z żądanym wskaźnikiem klasy przed wywołaniem samej funkcji/procedury. – ChrisB

+0

Brak adaptera jest warstwą między oryginalnym tym C++ a Twoim kodem Delphi. Może wywoływać to C++ i ponownie wywozi go jako właściwy interfejs bezpieczeństwa między interfejsami. –

+1

Zobacz artykuł, o którym wspomniałem w [moja odpowiedź] (http://stackoverflow.com/a/32035356/95954). Znacznie opisuje kod adaptera. –

3

Jak już powiedział Dawid, można dalej używać asemblera, ale istnieją lepsze sposoby. Napisałem artykuł o nazwie "Using C++ Objects in Delphi" że decribes obszernie, z kodem, w jaki sposób można wykorzystać obie alternatywy:

  • Napisz warstwa C, które wywozi funkcji C-stylu, że po prostu użyć klasy C++ i narazić każdej z metod, proste funkcje. Jest to dość proste, ale nieco niewygodne w użyciu od strony Delphi.
  • Napisz warstwę COM, która nie jest tak łatwa, jak się wydaje. Potrzebowałem dość pomocy od guru C++, aby zrobić to dobrze. W artykule opisano kroki i można je zastosować od 1 do 1 w swoich klasach.

Ja osobiście wolałbym warstwę COM. Jest o wiele łatwiejszy w użyciu od strony Delphi.

W artykule opisano także kilka problemów, które można napotkać podczas pisania takiego kodu lub używania takich obiektów. Przeczytaj to wszystko.