Domanda

Questa è una domanda a cui ho sempre desiderato conoscere la risposta, ma che non ho mai fatto.

Come viene chiamato il codice scritto da una lingua, in particolare una lingua interpretata, dal codice scritto da una lingua compilata.

Ad esempio, supponiamo che sto scrivendo un gioco in C ++ e che esternalizzi parte del comportamento dell'IA da scrivere in Scheme. In che modo il codice scritto in Scheme arriva a un punto utilizzabile dal codice C ++ compilato? Come viene utilizzato dal codice sorgente C ++ e come viene utilizzato dal codice compilato C ++? C'è una differenza nel modo in cui viene utilizzato?

correlati

  

Come interagiscono più lingue in un progetto?

È stato utile?

Soluzione

Non esiste una risposta unica alla domanda che funziona ovunque. In generale, la risposta è che le due lingue devono concordare su "qualcosa". - un insieme o regole o un "protocollo di chiamata".

A un livello elevato, qualsiasi protocollo deve specificare tre cose:

  • " discovery " ;: come trovarsi l'uno sull'altro.
  • " linking " ;: Come stabilire la connessione (dopo essersi conosciuti)
  • " Invocation " ;: Come inoltrare richieste l'una all'altra.

I dettagli dipendono fortemente dal protocollo stesso.

A volte le due lingue cospirano per lavorare insieme. A volte le due lingue accettano di supportare alcuni protocolli non definiti. Al giorno d'oggi, il sistema operativo o "ambiente di runtime" (.NET e Java) sono spesso coinvolti. A volte l'abilità va solo in un modo ("A" può chiamare "B", ma "B" non può chiamare "A").

Si noti che questo è lo stesso problema che deve affrontare qualsiasi lingua durante la comunicazione con il sistema operativo. Il kernel di Linux non è scritto in Scheme, sai!

Vediamo alcune risposte tipiche dal mondo di Windows:

  • C con C ++ : C ++ utilizza una variazione contorta ("alterata") del protocollo "C". C ++ può chiamare in C e C può chiamare in C ++ (anche se a volte i nomi possono essere piuttosto disordinati e potrebbe essere necessario un aiuto esterno per tradurre i nomi). Questo non è solo Windows; è generalmente vero in tutte le piattaforme che supportano entrambi. I sistemi operativi più popolari utilizzano un protocollo "quot" C " anche.

  • VB6 rispetto alla maggior parte delle lingue : il metodo preferito da VB6 è il "protocollo COM". Altre lingue devono essere in grado di scrivere oggetti COM per essere utilizzabili da VB6. VB6 può anche produrre oggetti COM (sebbene non tutte le possibili variazioni di oggetti COM).

    VB6 può anche parlare di una variazione molto limitata del protocollo "C" e quindi solo per effettuare chiamate all'esterno: non può creare oggetti con cui è possibile parlare direttamente tramite il protocollo "C".

  • Lingue .NET : tutte le lingue .NET comunicano compilate nella stessa lingua di basso livello (IL). Il runtime gestisce la comunicazione e da quel punto di vista, sembrano tutti nella stessa lingua.

  • VBScript rispetto ad altre lingue : VBScript può parlare solo un sottoinsieme del protocollo COM.

Un'altra nota: SOAP " Servizi Web " è davvero un "protocollo di chiamata" anche, come molti altri protocolli basati sul web che stanno diventando popolari. Dopotutto, si tratta di parlare con un codice scritto in una lingua diversa (e di eseguirlo in una casella diversa!)

Altri suggerimenti

In genere il codice C ++ invoca un interprete per il linguaggio di scripting. Il grado di interazione tra il codice compilato e lo scripting dipende dall'interprete ma c'è sempre un modo per passare i dati tra i due. A seconda dell'interprete, potrebbe essere possibile manipolare gli oggetti su un lato dall'altro lato, come una funzione C ++ che chiama un metodo su un oggetto Ruby. Potrebbe anche esserci un modo per controllare l'esecuzione dell'uno dall'altro.

Esiste un protocollo per comunicare i moduli. Ecco una panoramica di alto livello e ampia di come funziona:

  1. Viene creata una libreria per il codice che si desidera 'condividere'. Questi sono comunemente chiamati DLL o SO a seconda della piattaforma.
  2. Ogni funzione che vuoi esporre (punto di ingresso) sarà disponibile al mondo esterno a cui associarti. Esistono protocolli su come associare come la convenzione di chiamata che specifica l'ordine in cui vengono passati i parametri, chi pulisce lo stack, quanti parametri vengono memorizzati nei registri e quali, ecc. Vedi cdecl, stdcall, ecc. Per esempi di chiamata convenzioni qui .
  3. Il modulo chiamante verrà quindi associato staticamente o dinamicamente alla libreria condivisa.
  4. Una volta che la libreria chiamante è associata alla libreria condivisa, può quindi specificare che desidera associare un determinato punto di ingresso. Questo viene generalmente fatto per nome, tuttavia la maggior parte delle piattaforme offre anche l'opzione di associazione per indice (più veloce, ma più fragile se il modulo cambia e i punti di ingresso vengono riordinati).
  5. In genere dichiarerai anche la funzione che vuoi chiamare nel tuo modulo da qualche parte in modo che la tua lingua possa fare un controllo statico del tipo, sapere qual è la convenzione di chiamata ecc.

Per il tuo scenario di chiamata di Scheme da C ++, l'interprete Schema molto probabilmente esporta una funzione che si lega dinamicamente a una funzione / oggetto Scheme e la chiama. Se il modulo Scheme viene compilato, probabilmente ha la possibilità di esportare un punto di ingresso in modo che il modulo C ++ possa collegarsi a quello. Non ho molta familiarità con Scheme, quindi qualcun altro può probabilmente rispondere meglio ai dettagli di quel particolare legame di me.

Puoi anche integrare i due ambienti senza dover compilare la libreria dell'interprete all'interno del tuo eseguibile. Mantieni la tua exe e la Schee exe come programmi separati sul tuo sistema. Dal tuo exe principale puoi scrivere il tuo codice Scheme in un file quindi usare system () o exec () per eseguire l'interprete dello schema. Quindi si analizza l'output dell'interprete dello schema.

L'approccio suggerito sopra mantiene separati gli ex e non devi preoccuparti delle dipendenze di terze parti, possono essere significative. Anche i problemi rimangono contenuti in un ex o nell'altro.

Se l'esecuzione di un exe separato non soddisfa i requisiti di prestazione, è possibile elaborare un protocollo in cui l'interprete Scheme diventa un server. È necessario scrivere alcune funzioni dello schema che attendono l'input su un socket o su un file, valutare quell'input e quindi emettere il risultato sullo stesso socket o su un altro file. Un'altra versione di questo è guardare ai server esistenti che potrebbero già essere in esecuzione sul tuo interprete, ad esempio apache ha moduli che consentono di scrivere codice in molte lingue.

Se stai effettivamente cercando strumenti per fare una cosa del genere, come risposta di Adam, vedi swig .

Da un punto di vista teorico, quando il programma A deve usare le risorse (classe / funzioni / ecc.) dal programma B, si tratta di passare alcune informazioni da A a B, e di recuperare alcune informazioni o alcune azioni eseguite. Quindi deve esserci un modo fornito da B che consenta ad A di trasmettere informazioni e ottenere risultati.

In pratica, di solito spetta alle lingue gestire questo processo: la lingua B (il programma B è scritto in) genererà un protocollo e renderà disponibili le risorse in B in modo predefinito, quindi la lingua A (programma A è scritto in) fornirà alcune utilità / framework per aiutare a invocare le risorse esposte e ottenere risultati seguendo il protocollo B.

Per essere più specifici alla tua domanda, per i linguaggi interpretati, il processo è abbastanza universale, il protocollo è normalmente tra le righe del parametro della riga di comando, la richiesta HTTP e altri modi di trasmettere il testo normale. Prendiamo il primo esempio, il programma B riceverà una chiamata dalla richiesta HTTP come input, quindi elaborerà la richiesta da lì in poi. Il formato effettivo dell'input è totalmente deciso dal programma B.

Cose come SOAP ed ecc., sono solo un modo per regolare i programmi in modo da ricevere input in uno standard comunemente concordato.

Sono passati circa un decennio, ma ho fatto esattamente questo per il mio capstone senior (beh, ho costruito una rete neurale a propulsione posteriore in C, e ho usato un programma per insegnarlo). La versione di Scheme che stavo usando aveva un compilatore e un intero, e sono stato in grado di costruirlo come file .o. Non conosco la versione dello schema che stavo eseguendo, ma sembra che RScheme trasformerà il codice dello schema in C.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top