2015-08-15 7 views
9

Ho bisogno di chiamare funzioni non statici C++ utenteDelphi thiscall convenzione di chiamata

Quindi ho bisogno di usare il thiscall chiama la convenzione.

Delphi non supporta questa convenzione di chiamata.

Quindi prima di poter chiamare qualsiasi funzione membro devo spingere manualmente i parametri nello stack.

asm 
    mov ecx, myClassPointer 
    end; 

Questo funziona bene ma sto cercando un modo migliore per farlo.

Al momento sto chiamando il codice asm ogni volta con il classpointer prima di chiamare la funzione, il che non è bello.

Poiché non sono un esperto di Delphi mi chiedo se è possibile dichiarare la propria convenzione di chiamata o automatizzare la chiamata di questi metodi di classe classica.

+2

Ho scritto alcuni [questo adattatore per le interfacce Rich-Edit di Microsoft] (http://www.cs.wisc.edu/~rkennedy/windowless-rtf), che ha erroneamente omesso le convenzioni di chiamata. I miei adattatori avvolgono le interfacce in entrambe le direzioni, in modo che il codice Delphi possa chiamare il codice di Microsoft e il codice di Microsoft può richiamare un'interfaccia di Delphi, e ciascuna parte pensa che l'altra stia fornendo la convenzione di chiamata prevista. Forse lo troveresti utile. –

risposta

4

La convenzione di chiamata Delphi register utilizza registri per i primi tre parametri. I primi due sono EAX e EDX, che non sono utilizzati nella convenzione di chiamata thiscall e possono essere impostati su qualsiasi cosa tu voglia.Il terzo di questi registri è ECX.

thiscall passa tutti gli argomenti nello stack e register passa gli argomenti rimanenti nello stack. Sia lo register e lo thiscall hanno gli argomenti puliti del callee passati sullo stack.

Quindi, ciò che si può fare è dichiarare una funzione register, con parametri fittizi per EAX e EDX. Puoi ancora racchiuderlo in una funzione diversa per rendere più semplice la chiamata, ma almeno ora la funzione wrapper può essere dichiarata inline.

Nota che l'ordine in cui gli argomenti vengono spinti nello stack è diverso tra thiscall e register, quindi è necessario invertire i parametri per farlo corrispondere.

5

sono disponibili le seguenti opzioni: adattatori

  • Scrivere in ASM per richiamare la funzione. Questa è la tua soluzione attuale e, come sai, l'approccio è fragile e scomodo.
  • Scrivere un adattatore C++ che presenta un'interfaccia amichevole.

Quest'ultima opzione è, a mio avviso, la soluzione corretta. Il codice C++ non è adatto per l'interoperabilità. Esporre le classi C++ attraverso l'interoperabilità è semplicemente sbagliato. Mette richieste irragionevoli al consumatore. Gli approcci ragionevoli includono COM e l'interop in stile C semplice come trovato in Win32.

Scrivere una DLL C++ adattabile che consuma le classi C++ irragionevoli ed espone un'interfaccia di interoperabilità appropriata. L'adattatore è scritto in C++ e quindi è in grado di utilizzare il codice C++. Ma poi esporta una variante interoperabile dell'interfaccia che può essere facilmente chiamata da qualsiasi catena di strumenti.

+0

Potresti per favore approfondire la parte degli adattatori. Non ne ho mai sentito parlare in termini di chiamate di funzione delphi. Fondamentalmente dovrebbe chiamare il codice asm con il puntatore di classe desiderato prima di chiamare la funzione/procedura stessa. – ChrisB

+0

No, l'adattatore è un livello compreso tra l'originale thiscall C++ e il codice Delphi. Può chiamare thiscall C++ e lo ri-esporta come un'interfaccia di sicurezza sicura. –

+1

Vedere l'articolo che ho citato in [la mia risposta] (http://stackoverflow.com/a/32035356/95954). Descrive ampiamente il codice dell'adattatore. –

3

Come già detto, puoi continuare ad usare l'assemblatore, ma ci sono modi migliori. Ho scritto un articolo intitolato "Using C++ Objects in Delphi" che decribes ampiamente, con il codice, come è possibile utilizzare entrambe le alternative praticabili:

  • Scrivi uno strato C che esporta le funzioni in stile C che utilizzano semplicemente la classe C++ e espongono ognuno dei metodi di funzioni semplici. Questo è piuttosto semplice, ma un po 'scomodo da usare dal lato Delphi.
  • Scrivere un livello COM, che non è così facile come sembra. Ho avuto bisogno di un po 'di aiuto da un guru del C++ per farlo nel modo giusto. L'articolo descrive i passaggi e puoi applicarli 1 a 1 alla tua classe.

Personalmente preferirei comunque il livello COM. È molto più facile da usare dal lato Delphi.

L'articolo descrive anche alcuni dei problemi che si possono incontrare durante la scrittura di tale codice o l'utilizzo di tali oggetti. Leggi tutto.

Problemi correlati