Newsgroup: it.comp.java
Titolo: integrazione java/C++

Ciao a tutti, avrei bisogno di utilizzare classi java da un programma C++.
Avete idea se e' possibile una cosa del genere?
Grazie!
Ciao by Allanon
PS: so che e' ovviamente possiblle una soluzione con meccanismi IPC ma i
miei committenti gradirebbero
una soluzione piu' integrata... :-(

 Avete idea se e' possibile una cosa del genere?
Usando JNI puoi richiamare una Classe Java da un programma C/C++ e
viceversa. Vedi la documentazione di JNI su 
http://java.sun.com
.
Davide

 Avete idea se e' possibile una cosa del genere?
Si - l'idea e' che lanci una JVM dal codice C/C++ (usando l'invocation 
API, specificata insieme a JNI) e poi usi i normali meccanismi JNI per 
creare oggetti, invocarci metodi, eccetera.
Normalmente, per ovvi motivi, conviene fare quanto piu' lavoro possibile di 
chiamate Java in ...Java. Spesso quindi si costruisce una classettina 
apposta il cui unico scopo e' di ricevere input dal codice C, fare il 
lavoro preparatorio e coordinare il lavoro degli oggetti originali e 
ritornare il risultato nella forma piu' semplice da gestire dal codice C. 
Il codice C/JNI si limita quindi ad interagire con i metodi di queste 
classi. 
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

 creare oggetti, invocarci metodi, eccetera.
grazie, ancora qualche dubbio:
La classe java da chiamare usa una API che usa thread e chiama degli Handler
ogni tot secondi
e in condizioni particolari.
c'e' qualche problema a gestire queste problematiche di multithreading?
Grazie
Allanon

 wrote in
news:ai89u3$11m99a$
1...@ID-139431.news.dfncis.de
: 

Dipende. In genere no. Tieni presente che quello che succede e' che una JVM 
viene lanciata ed e' pronta a servire richieste. "Lanciata" significa che 
viene inizializzata e messa nello stato iniziale, ma di per se non sta 
"facendo" nulla. E' - a tutti gli effetti - equiparabile ad un'oggetto C++ 
di classe "JVM" appena creato, o ad una DLL/shared library appena caricata. 
Alla prima invocazione di metodo, l'invocazione viene in genere eseguita 
nel thread di s/o in cui sta girando il codice C. Se quest'invocazione 
genera altri thread Java - dipende da come sono implementati dalla 
particolare JVM: ad esempio, se sono thread 'emulati' il thread di s/o 
restera' uno solo; se sono implementati via thread nativi, avrai vari 
thread di s/o che vengono generati ed entrano in competizione col thread 
principale. 
A seconda di come il tuo s/o gestisce i thread (ricorda, sei in ambiente 
C/C++ e che quindi non garantisce portabilita' per quanto riguarda i 
thread) potrai avere effetti diversi, e la necessita' di rilasciare 
manualmente il controllo del thread di s/o in cui gira il codice C/C++ o 
meno. I thread Java seguono la solita semantica di concorrenza, pero' _solo 
quando il thread di s/o che fa girare la JVM non e' asleep_. Con sistemi 
operativi tipo win32 o quasi tutti gli unix questo non e' un gran problema, 
perche' implementano politiche di schedulazione per i thread che sono 
ragionevoli.
Siccome non ti interessa la portabilita', comunque, il trucco e' provare e 
vedere che succede, e fare il tuning del codice C/C++ in modo da dare alla 
JVM una chance di girare.


 JVM una chance di girare.
grazie ancora.
secondo te questo tutorial e' valido?
http://java.sun.com/docs/books/tutorial/native1.1/TOC.html
e' l'unico comprensibile che ho trovato per adesso...
pero' penso sia una vecchia versione. o sbaglio?
Allanon

 secondo te questo tutorial e' valido?
Non saprei, dato che non l'ho mai letto. :(
La cosa che usai io e' la guida/specifica a JNI (all'epoca, col JDK1.1, ma 
ho guardato e c'e' anche nei docs dell'1.4 insieme ad un paio di updates). 
Ma - se mastichi C/C++ s'intende - non c'e' niente di particolarmente 
complicato. L'unica cosa, tutte le funzioni sono specificate con la 
signature C, che per molte comprende il puntatore ad una struttura JEnv 
come primo parametro; ma compilando da C++ in effetti si usa il leggero 
strato C++ che incapsula queste funzioni come metodi di un oggetto JEnv - e 
'sta cosa all'epoca non era scritta da nessuna parte (cfr. <jni.h>, i pezzi 
dentro #ifdef _cplusplus). 
Quindi ogni funzione la cui signature C e' del tipo
      <returntype> pincopallo(JEnv *env, ..altri parametri.. ) 
da codice C++ si invoca con
    	env->pincopallo(..altri parametri.. )
Occhio a ricordarsi di rilasciare i buffer per le stringhe C derivanti da 
oggetti String (che sono locked in modo che i relativi oggetti Java non 
vengano garbage collected mentre il codice C ne sta facendo uso), che e' 
l'unica cosa un po' particolare di JNI.
Anche, se si carica un classe si deve usare in genere il nome "interno" 
(che e' lo stesso del nome esterno, solo con uno slash '/' invece di un 
punto '.' - ad esempio java.lang.String ha nome interno java/lang/String), 
e per "nominare" un metodo (e quindi ottenerne l'handle) bisogna capire 
qual'e' la signature interna del metodo - il trucco e' usare javap -s sulla 
classe da invocare e leggerla ;-)


 dentro #ifdef _cplusplus).
ok, ho ottenuto qualche risultato, ossia ho caricato la JVM e  invocato il
main che invoca un altro metodo statico.
il problema nasce quando devo istanziare un oggetto ed invocarne un
metodo.... non ci riesco!!!!!
e nei tutorial che ho guardato in rete non l'ho trovato (mea culpa,
sicuramente e' passato davanti ai miei occhi...)
Se qualcuno mi sa dire come fare...
Grazie
Allanon

 metodo.... non ci riesco!!!!!
Per esempio, sei hai una classe C con un costruttore C(String s) un metodo 
int m(), devi
1) recuperare un handle a C. E' equivalente a Class.forName() in Java:
jclass cls = env->FindClass("C");
2) allocare la memoria un'istanza con AllocObject
jobject obj = env->AllocObject(cls);
3) terminare l'instanziazione invocando il costruttore desiderato. Il 
costruttore e' un metodo, il cui nome e' "<init>" (e ha 'void' come tipo di 
ritorno) quindi devi 
 3.1) Scoprire la signature: per un metodo che ritorna void e ha un singolo
      parametro di classe java.lang.String, la signature
      e' "(Ljava/lang/String;)V"
 3.2) Ottenere un handle al metodo:
   jmethodID cId = env->GetMethodID("<init>","(Ljava/lang/String;)V");
 3.3) Allocare, se necessario, i parametri di costruzione. Siccome nel             
nostro caso il parametro di costruzione e' una java.lang.String, usiamo 
NewStringUTF():
   jstring s = env->NewStringUTF("pippo");
 3.4) Invocare il metodo di costruzione, passando i parameteri:
   env->CallVoidMethod(obj, cId, s);
4.0) Stessa cosa per ottenere un handle al metodo m() e invocarlo.


 ritorno) quindi devi
[cut]
grazie dell'hint anche se finalmente ho trovato una doc valida sul sito
della SUN (lo dicevo che doveva esserci!)
l'unica cosa che ho notato e che tu fai "AllocObject" poi
"GetMethodID("<init>"..." ed infine "CallVoidMethod"
Io invece ho usato:
 //trovo il ctor
 mid=env->GetMethodID(cls, "<init>", "()V");
 //costruisco l'oggetto con il ctor selezionato
 jobj=env->NewObject(cls, mid);
e' uguale? io penso di si, in pratica tu prima crei una zona di mem e poi la
inizializzi, io faccio tutto insieme...(o no?)
Grazie e ciao
Allanon

 e' uguale? 
Si'. :)
