2009-09-16 9 views
12

Sto scrivendo un'applicazione Java che utilizza una libreria C++ tramite un'interfaccia JNI. La libreria C++ crea oggetti di tipo Foo, che sono debitamente passati attraverso JNI a Java.Condivisione di flussi di output tramite un'interfaccia JNI

Supponiamo che la biblioteca ha una funzione di uscita

void Foo::print(std::ostream &os) 

e ho un Java OutputStream out. Come posso richiamare Foo::print da Java in modo che l'output venga visualizzato su out? Esiste un modo per forzare lo OutputStream a std::ostream nel livello JNI? Posso acquisire l'output in un buffer del layer JNI e quindi copiarlo in out?

risposta

0

Come posso richiamare Foo :: print da Java in modo che l'output venga visualizzato in uscita?

Concettualmente parlando, il modo per ottenere Foo :: print (...) di scrivere a un'istanza Java OutputStream esistente è quello di scrivere un'implementazione std :: ostream C++ che fa in realtà un callback in Java per fare uscita .

Sembra possibile, ma non vorrei scrivere/mantenere il codice. In fase di esecuzione, le chiamate passano da Java -> C++ -> Java, e ci sono molte opportunità per commettere errori che causeranno il blocco casuale della JVM.

C'è un modo per costringere il OutputStream ad uno std :: ostream nello strato JNI?

AFAIK n.

Posso catturare l'output in un buffer lo strato JNI e quindi copiarlo in fuori?

Intendi qualcosa di simile a questo?

MyJNIThing m = ... 
    int myOstream = m.createMemoryBackedOStream(...); // native method 
    ... 
    m.someMethodWrapper(... myOStream); // native method 
    ... 
    byte[] data = m.getCapturedData(myOStream); // native method 
    out.write(data); 

Probabilmente si può fare una cosa del genere ... il lavoro in una buona giornata con un vento in poppa.

Ma penso che dovresti davvero mirare ad eliminare il codice C++ piuttosto che cercare di fare cose sempre più complicate attraverso JNI. IMO, JNI dovrebbe essere usato solo come ultima risorsa, e non una scorciatoia per evitare la ricodifica di roba in Java.

+0

Reimplementare la libreria in Java non è un'opzione (è ampia, matura e ad alte prestazioni). –

+0

Forse non dovresti provare a chiamarlo da Java allora. Il mio punto è che è probabile che crei molto dolore per te stesso e per le persone che devono mantenere il tuo codice. –

+2

Mentre sono d'accordo, il codice JNI è difficile dire che si dovrebbe assolutamente evitare che non sia giusto. C'è sicuramente una Place for JNI, in particolare con grandi progetti legacy come l'op menzionato e nel mio caso le API di terze parti che devi usare per portare a termine il lavoro. Questa è una domanda molto valida, anche io cerco una risposta. – Cliff

1

Ho pubblicato uno writeup on my blog dettaglio la mia recente esperienza con questo stesso problema. In generale, si desidera evitare di provare a connettere un flusso di input o di output a un client in qualsiasi lingua in quanto implica thread. È possibile fornire in modo incrementale i dati utilizzando i callback.

6

Implementare un ostream C++ che registra buffer (fino ad alcune dimensioni impostate) prima di svuotare quelle scritture su un OutputStream java tramite JNI.

Sul lato Java, è possibile utilizzare un'istanza di OutputStream normale oppure è possibile implementare l'accodamento dei blocchi del buffer (essenzialmente byte []) per evitare qualsiasi possibile conflitto tra i thread. Il flusso di output reale viene utilizzato solo da un'attività su un altro thread che estrae i blocchi dalla coda e li scrive su OutpuStream.Non posso dire se questo sia necessario o meno a questo livello di dettaglio - potreste trovare la scrittura direttamente nel flusso di output dalle opere di JNI.

Non condivido le preoccupazioni degli altri poster con JNI e non vedo alcun problema con l'utilizzo di JNI per questo. Certo, i tuoi manutentori dovranno conoscere le loro cose, ma questo è tutto, e la complessità del livello Java/C++ può essere gestita con documentazione, esempi e casi di test. In passato, ho implementato un bridge COM Java <> con un'interfaccia piuttosto chiacchierone - nessun problema con le prestazioni, il threading o la manutenzione.

Data una scelta totalmente libera, non ci sarebbe JNI, ma per me ha salvato la giornata rendendo possibile la stretta integrazione di sistemi altrimenti incompatibili.

+0

Punti bonus per non colpire JNI. – rdb

Problemi correlati