2015-08-15 4 views
9

Ich brauche nicht-statische C++ Funktionen MitgliedDelphi Thiscall-Aufrufkonvention

Daher muss ich anrufen, um den thiscall Aufrufkonvention verwenden.

Delphi unterstützt diese Aufrufkonvention nicht.

Bevor ich also eine der Member-Funktionen aufrufen kann, muss ich manuell die Parameter im Stack drücken.

asm 
    mov ecx, myClassPointer 
    end; 

Das funktioniert gut, aber ich suche nach einer besseren Möglichkeit, dies zu tun.

Im Moment rufe ich den Asm-Code immer mit dem Classpointer auf, bevor ich die Funktion aufruft, was nicht nett ist.

Da ich kein Delphi-Experte bin, frage ich mich, ob Sie Ihre eigene Aufrufkonvention deklarieren oder den Aufruf dieser thiscall Klassenmethoden automatisieren können.

+2

Ich schrieb einige [Thiscall Adapter für Microsoft Rich-Edit-Schnittstellen] (http://www.cs.wisc.edu/~rkennedy/windowless-rtf), die fälschlicherweise die Aufrufkonventionen weggelassen. Meine Adapter umschließen Schnittstellen in beide Richtungen, so dass Delphi-Code den Code von Microsoft aufrufen kann und Microsoft-Code kann zu einer Delphi-Schnittstelle zurückrufen, und jede Seite denkt, dass die andere die erwartete Aufrufkonvention bereitstellt. Vielleicht findest du es nützlich. –

Antwort

4

Delphis register Aufrufkonvention verwendet Register für die ersten drei Parameter. Die ersten beiden sind EAX und EDX, die in der thiscall Aufrufkonvention unbenutzt sind und beliebig gesetzt werden können.Das dritte dieser Register ist ECX.

thiscall übergibt alle Argumente auf dem Stapel und register übergibt die verbleibenden Argumente auf dem Stapel. Sowohl register als auch thiscall haben die Aufräumargumente, die auf dem Stapel übergeben werden.

Sie können also eine register Funktion mit Dummy-Parametern für EAX und EDX deklarieren. Sie können dies jedoch in eine andere Funktion einfügen, um den Aufruf zu erleichtern, aber diese Wrapper-Funktion kann jetzt zumindest als inline deklariert werden.

Beachten Sie jedoch, dass die Reihenfolge, in der Argumente auf dem Stapel abgelegt werden, zwischen thiscall und register unterschiedlich ist. Daher müssen Sie die Parameter umkehren, damit sie übereinstimmen.

5

Sie haben folgende Möglichkeiten:

  • schreiben Adapter in asm um die Funktion aufzurufen. Dies ist Ihre derzeitige Lösung, und wie Sie wissen, ist der Ansatz spröde und peinlich.
  • Schreiben Sie einen C++ - Adapter, der eine interop-freundliche Schnittstelle darstellt.

Die letztere Option ist aus meiner Sicht die richtige Lösung. Der C++ Code ist nicht für Interop geeignet. C++ Klassen über Interop zu exponieren ist einfach falsch. Es stellt unvernünftige Forderungen an den Verbraucher. Angemessene Ansätze umfassen COM und Plain C Interop wie in Win32.

Schreiben Sie eine adaptierende C++ - DLL, die die unangemessenen C++ - Klassen verbraucht und eine geeignete Schnittstelle für Interop-Benutzer verfügbar macht. Der Adapter ist in C++ geschrieben und kann daher den C++ - Code konsumieren. Aber dann exportiert es eine interop-freundliche Variante der Schnittstelle, die aus jeder Werkzeugkette leicht aufgerufen werden kann.

+0

Könnten Sie bitte etwas über den Adapterteil ausarbeiten? Davon habe ich in Terminen des Delphi-Funktionsaufrufs noch nie gehört. Im Grunde sollte es den Asm-Code mit dem gewünschten Klassenzeiger aufrufen, bevor die Funktion/Prozedur selbst aufgerufen wird. – ChrisB

+0

Nein, der Adapter ist eine Ebene zwischen dem Original thiscall C++ und Ihrem Delphi-Code. Es kann den Thiscall C++ aufrufen und es als eine richtige Interop-sichere Schnittstelle erneut exportieren. –

+1

Siehe den Artikel, den ich in [meine Antwort] erwähnte (http://stackoverflow.com/a/32035356/95954). Es beschreibt den Adaptercode ausführlich. –

3

Wie David bereits gesagt hat, können Sie Assembler verwenden, aber es gibt bessere Möglichkeiten. Ich schrieb einen Artikel namens "Using C++ Objects in Delphi", die umfassend, mit Code decribes, wie Sie beiden Alternativen verwenden:

  • eine Schicht C schreiben, die C-Stil Funktionen exportiert, die einfach die C++ Klasse verwenden, und jedes des Verfahrens aussetzen als einfache Funktionen. Dies ist ziemlich einfach, aber ein wenig umständlich von der Delphi-Seite zu verwenden.
  • Schreiben Sie eine COM-Ebene, die nicht so einfach ist wie es klingt. Ich brauchte ziemlich viel Hilfe von einem C++ - Guru, um es richtig zu machen. Der Artikel beschreibt die Schritte und Sie können sie 1 zu 1 auf Ihre Klasse (n) anwenden.

Ich würde persönlich die COM-Ebene bevorzugen. Es ist viel einfacher von der Delphi-Seite zu verwenden.

Der Artikel beschreibt auch einige der Probleme, die beim Schreiben von Code oder bei der Verwendung solcher Objekte auftreten können. Lesen Sie alles.