2013-05-28 7 views
16

Ho un codice C++ esistente che esegue l'elaborazione numerica all'interno di un'applicazione C++ autonoma. Ora voglio usare quel codice all'interno di una nuova applicazione node.js.node-ffi vs. estensione del nodo per l'accesso alla funzionalità C++ esistente

Researching come accedere a codice C++ da node.js, due opzioni venire:

  1. Scrivi un'estensione node.js
  2. Usa node-ffi

nodo-FFI sembra una buona opzione per accedere alle librerie esistenti, ma ho ragione a pensare se uso node-ffi dovrei scrivere un wrapper C per rendere accessibile il mio C++? (Questo era l'unico modo per far funzionare un semplice caso di test su Windows con Visual Studio).

Per il mio caso in cui il mio codice sorgente è già in C++, non C, quali sono le considerazioni nella scelta tra le due opzioni sopra?

+0

Usi un sacco di ereditarietà, funzioni virtuali e modelli nel codice – aaronman

+0

Nessun modello. Nessuna funzione virtuale. Qualche eredità, anche se potrei modificare il codice per evitarlo se necessario. – pancake

+0

Penso che sarebbe relativamente facile scrivere i wrapper di – aaronman

risposta

19

FFI funziona con librerie C dinamiche. Ciò significa che devi esporre esternamente la tua libreria dinamica. In C++, si esegue questa operazione con extern "C", in questo modo:

#ifdef __cplusplus 
extern "C" { 
#endif 

int foo (int param){ 
    int ret = 0; 
    // do C++ things 
    return ret; 
} 

int bar(){ 
    int ret = 0; 
    // do C++ things 
    return ret; 
} 

#ifdef __cplusplus 
} 
#endif 

Questo renderà la vostra funzione C++ a disposizione C-cose, come un metodo libreria dinamica.

Ecco come si avvolgono questo in javascript, dopo aver compilato il vostro lib C++ come libmylibrary.dll/.so:

var ffi = require('ffi'); 

var mylibrary = ffi.Library('libmylibrary', { 
    "foo": [ "int", ["int"] ], 
    "bar": [ "int", [] ] 
}); 

Ci sono un sacco più fredde cose che si possono fare. Controllalo, here

Se questa è una libreria di nodi, inserisci i tuoi metodi in module.exports. Ecco un esempio completo di un involucro del codice C++ sopra, con sincrone & metodi asincroni:

var ffi = require('ffi'); 

var mylibrary = ffi.Library('libmylibrary', { 
    "foo": [ "int", ["int"] ], 
    "bar": [ "int", [] ] 
}); 

module.exports = { 
    fooSync : mylibrary.foo, 
    foo: mylibrary.foo.async, 
    barSync : mylibrary.bar, 
    bar: mylibrary.bar.async 
}; 

Non ho usato node-ffi-generate, ma sembra piuttosto fresco per la generazione di questo genere di wrapper per voi.

Se ho salvato questo file come mylibrary.js, ho potuto usare in questo modo: "è meglio"

var mylib = require('./mylibrary.js'); 

var num = mylib.fooSync(1); 

// or 

mylib.foo(1, function(er, num){ 

}); 

Per quanto riguarda la domanda di Penso di sì, per la maggior parte delle cose. Se rendi i tuoi metodi extern C, funzioneranno in quasi tutte le altre lingue, alcune delle quali hanno anche FFI, quindi dovresti scrivere l'equivalente semplice di quanto sopra in qualsiasi lingua di destinazione. Questo significa pochissimo codice da mantenere, oltre al semplice "caricare C++ lib", e "scherzare con la sua firma per sentirsi bene per il linguaggio X". Non è specifico per il nodo. Un altro bonus è per le comuni librerie condivise (come sqlite, dato nell'esempio tutorial). Forse non ti interessa esattamente quale versione hanno, o vuoi avvolgerla con più codice C++, che deve essere compilato per usarlo. Usando FFI, puoi racchiudere una lib pre-compilata/installata con solo javascript.

+0

Ottima risposta dettagliata, grazie mille! È passato un po 'di tempo da quando ho scritto la domanda, e ora sarei d'accordo sul fatto che ritenere che l'utilizzo della rotta FFI sia probabilmente più semplice della scrittura di un'estensione. node-ffi-generate sembra interessante. – pancake

Problemi correlati