View Full Version : [Java] Ibridare il java
palombaro
28-09-2003, 11:12
Salve a tutti vorrei avere delle informazioni su come utilizzare
la java native interface avevo trovato una guida s mokabyte
ma il mio piccolo programmino non funzionava potete aiutarmi???
palombaro
29-09-2003, 09:45
volevo creare un programma in java che si appoggiasse
al c attraverso l' uso di metodi nativi. non ho ben capito la procedura che devo esegure per scrivere il codice in c creare la dll
e collegarla puoi aiutarmi?
Originariamente inviato da palombaro
volevo creare un programma in java che si appoggiasse
al c attraverso l' uso di metodi nativi. non ho ben capito la procedura che devo esegure per scrivere il codice in c creare la dll
e collegarla puoi aiutarmi?
scrivi la classe java dichiarando native i metodi che vuoi realizzare in C (o C++), lo compili, usi il programma javah per generare l'header e ne fai l'include nel tuo codice C. Compili il codice C realizzando una libreria condivisa e non un eseguibile e sei a posto.
Ricordati il loadLibrary nel tuo codice java per caricarla
Sfruttare metodi nativi è di una semplicità esilarante. Provo a spiegarlo io, spero di esserne all'altezza.
Usiamo come ambiente di sviluppo C/C++ Dev-Cpp, così evito di dover spiegare cose che non conosco circa la costruzione di una libreria condivisa.
Come esempio di applicazione che sfrutta un metodo nativo creeremo un fantastico programma che faccia la somma di due numeri interi usando una funzione C per la somma e Java per l'input-output.
1) Creiamo un sorgente "Glob.java" (il nome naturalmente non è importante).
class Glob {
Ora scriviamo il lato Java del metodo nativo. I metodi nativi devono essere presenti nel codice della classe che li usa: di solito si crea una classe "wrapper" che contenga tutti i metodi nativi e poi si usa questa classe dal lato Java. Noi abbiamo un solo metodo nativo, una classe dedicata mi sembra eccessiva.
Ecco la dichiarazione di un metodo nativo:
public native int eseguiSomma(int numero1, int numero2);
Nota l'assenza del corpo del metodo. In pratica è come se la clausola "native" indicasse al compilatore che il corpo del metodo è definito nella dll (che creeremo).
Ora carichiamo la libreria DLL (la chiamo dll perchè do per presupposto che si lavori in windows, ma non cambia un bel nulla su sistemi diversi a parte l'estensione).
static {
System.loadLibrary("somma");
}
Il blocco "static {...}" evita che la libreria sia caricata due volte dalla jvm in caso di chiamte plurime (o almeno credo...:D). Nota che il nome "somma" sottointende che la libreria che andremo a creare si chiami "somma".
Ora usiamo il metodo nativo. Dato l'obiettivo, il main è più che sufficiente.
public static void main(String[] args) {
try {
int n0=Integer.parseInt(a[0]);
int n1=Integer.parseInt(a[1]);
System.out.println(n0+" + "+n1+" = "+new Glob().eseguiSomma(n0,n1));
} catch(NumberFormatException e) {
e.printStackTrace();
System.exit(0);
} catch(ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.exit(0);
}
}
Abbiamo preso i primi due valori dell'array di String "args", supponendo che siano i due numeri da sommare e li abbiamo sommati usando il metodo nativo "eseguiSomma" della classe "Glob". A scanso di equivoci, quel "new Glob().eseguiSomma(n0, n1)" è fatto così solo perchè sta nel main, non perchè sia nativo. Per Java è un metodo come un altro e si usa nello stesso modo dei non-nativi.
Chiudiamo il corpo della classe con una parentesi graffa chiusa e siamo a posto. Di seguito il codice completo:
class Glob {
public native int eseguiSomma(int numero1, int numero2);
static {
System.loadLibrary("somma");
}
public static void main(String[] a) {
try {
int n0=Integer.parseInt(a[0]);
int n1=Integer.parseInt(a[1]);
System.out.println(n0+" + "+n1+" = "+new Glob().eseguiSomma(n0,n1));
} catch(NumberFormatException e) {
} catch(ArrayIndexOutOfBoundsException e) {
}
}
}
Salva il file sorgente, possibilmente creando prima una cartella "dedicata", così evitiamo un po' di confusione. Diciamo che la cartella è "c:\glob".
Compila il sorgente (c:\glob> javac Glob.java).
Ora creiamo l'header c che serve da "ponte" tra Java e la libreria dinamica. L'header (*.h) può essere creato automaticamente usando il tool "javah" contenuto nel JDK. Il comando è il seguente:
c:\glob> javah Glob
Nella cartella c:\glob dovresti avere adesso un file glob.h. Il file contiene il prototipo della funzione JNI corrispondente al metodo nativo "eseguiSomma". Quel prototipo deve essere implementato in un sorgente C e poi usato per costruire la libreria dinamica.
E facciamolo.
Apri Dev-Cpp.
Crea un nuovo progetto "c" usando uno wizard "dll" e chiama il progetto "somma".
Salva il progetto nella cartella "c:\glob" (per semplicità, la libreria può trovarsi in qualunque cartella del sistema operativo inclusa nella proprietà "java.library.path" o nella cartella del file .class).
Dev-cpp crea 2 file sorgente "dllmain.c" e "dll.h". Non ci servono pertanto chiudili senza salvarli.
Aggiungi un nuovo file sorgente al progetto (che salverai poi come "sommaImp.c" o con un altro nome, è irrilevante).
Qui implementiamo il metodo nativo (nel nostro caso usando C, potrebbe essere Assembler o un altro linguaggio, "nativo" significa "non-java").
Il nostro metodo nativo è elementare:
#include <jni.h>
#include "Glob.h"
#include <stdio.h>
JNIEXPORT jint JNICALL
Java_Glob_eseguiSomma (JNIEnv *env, jobject obj, jint num1, jint num2)
{
return num1+num2;
}
Trattandosi dell'implementazione di un metodo definito in un header puoi (devi) prendere come modello per il metodo il contenuto dell'header "Glob.h". C'è tutto un mondo dietro quel "JNIEXPORT jint JNICALL Java_Glob_eseguiSomma (JNIEnv *env, jobject obj, jint num1, jint num2)", solo che il post è già lungo senza...magari lo vediamo dopo?
Pima di compilare la nostra libreria occorre impostare i parametri del compilatore perchè trovi "jni.h".
L'header "jni" si trova nel jdk, cartella "include". Con dev-cpp la cosa si risolve così:
menu "strumenti"->"opzioni di compilazione". Nella finestra che compare seleziona la scheda "cartelle" quindi la scheda
"include C". Sopra il bottone "cancella invalida" c'è un pulsante che permette di selezionare una cartella del sistema.
Premilo e trova la cartella "c:\j2sdk1.4.2\include". Selezionala e poi premi "aggiungi". Fai lo stesso con la cartella
"c:\j2sdk1.4.2\include\win32". La posizione della cartella può cambiare a seconda dell'installazione del JDK presente sul tuo sistema operativo.
A questo punto non resta che lasciar compilare la libreria a Dev-cpp.
Fatto questo troverai nella cartella "c:\glob" un file "somma.dll".
E il gioco è fatto:
C:\JP\glob>java Glob 10 20
10 + 20 = 30
C:\JP\glob>
Dev-cpp lo trovi qui (http://sourceforge.net/projects/dev-cpp/).
Se ci sono problemi sai dove trovarci :)
Ciao.
palombaro
29-09-2003, 11:58
grazie a tutti avevo trovato un esmpietto su moka ma quando compilavo il codice in c mi diceva che non trovava le librerie standard del c!!!
ora provero grazie ancora!!!!!!!!!!!!!!!!!
palombaro
14-10-2003, 19:31
17 D:\prova\c++\sommaImp.c:1
jni.h: No such file or directory.
2 D:\prova\c++\sommaImp.c
In file included from sommaImp.c
17 D:\prova\c++\classenativa.h:2
jni.h: No such file or directory.
2 D:\prova\c++\sommaImp.c
In file included from sommaImp.c
15 D:\prova\c++\classenativa.h
parse error before `Java_classenativa_somma'
8 D:\prova\c++\sommaImp.c
parse error before `Java_classenativa_somma'
D:\prova\c++\Makefile.win
[Build Error] [sommaImp.o] Error 1
quando compilo.... la dll mi da sti errori cosa sbaglio?
Mi sembra che il compilatore che stai usando non trovi il file di intestazione jni.h. Forse dovresti controllare le opzioni di compilazione per vedere se è stato inserita la cartella in cui si trova il file.
palombaro
15-10-2003, 13:43
Originariamente inviato da PGI
Mi sembra che il compilatore che stai usando non trovi il file di intestazione jni.h. Forse dovresti controllare le opzioni di compilazione per vedere se è stato inserita la cartella in cui si trova il file.
la ho impostata nel profili di compilazione.... eppure mi dice che nn la trova che posso fare?
Prova a includerla con
#include "/percorsocompletoheader/jni.h"
anche se non e' la soluzione piu' elegante
palombaro
15-10-2003, 16:30
Originariamente inviato da lovaz
Prova a includerla con
#include "/percorsocompletoheader/jni.h"
anche se non e' la soluzione piu' elegante
ho provato gli errori si son centuplicati sono diventati
501
altri suggerimenti?
A scanso di equivoci prova a cercare il file jni.h e vedere dov'è.
Lo dico perchè è incluso nel JDK ma non nel JRE e ci sono ambienti di sviluppo (tipo Eclipse) che funzionano anche senza un jdk.
palombaro
15-10-2003, 18:22
stai nella cartella jbuilder9\jdk1.4\include
il compilatore c++ se ne sbatte però non le trova!!!!
help my!!!
Azz. Che compilatore usi?
A mali estremi...prova a cambiarlo (in giro per il web ce ne sono a palate anche freeware tipo gnu-gcc)
palombaro
16-10-2003, 08:15
uso quello consigliatomi qua!!!!!! il dev c++
non so + che pesci pigliare qualche suggerimento?
Questo è il contenuto della cartella "include C" che ho nelle opzioni ci compilazioni di dev-cpp
c:\Dev-cpp\include
c:\j2sdk1.4.2\include
c:\j2sdk1.4.2\win32
c:\j2sdk1.4.2\jre\bin\client
Trova gli omologhi sul tuo sistema e includili.
Ora prova ad aprire un nuovo progetto e scrivere questo in un nuovo file sorgente
progetto -> nuovo -> cartella "basic" -> empy project
Scegli come linguaggio "C"
Poi:
nuovo -> file sorgente -> aggiungi unità al progetto corrente "si"
#include "jni.h"
int main() {
return 0;
}
Compila e dimmi "è tutto ok adesso". Nel caso in cui funzioni, ti dico subito che non so perchè.
palombaro
16-10-2003, 11:39
no non funzia!! ora provo a scaricare e installare una jvm a parte magari è quella nel jburder che rompe le scatole.
Mi stupirebbe perchè la compilazione del file C non coinvolge la jvm.
Quali sono gli errori che ti da compilando:
#include "jni.h"
int main() {
return 0;
}
Così provo a riprodurli con il dev-cpp che ho qui
palombaro
16-10-2003, 12:23
mi dice che non trova il file jni.h
in dev-cpp c'è una cartella (opzioni di compilazione) "include" sia per C che C++. Hai impostato per entrambi le directory? (in teoria non cambia nulla perchè stiamo usando C e per c l'hai già impostato ma tecnologia fa rima con magia...)
prova a cambiare (nel file "minimo" che stiamo provando)
#include "jni.h"
con
#include "c:\j2sdk1.4.2....\jni.h" (cioè come segnalato da lovaz).
In questo caso, se trova il file jni.h dovrebbe dirti che non trova il resto...forse
palombaro
16-10-2003, 12:50
risoltoooooooooooo!:D :D :D :D :D :D :D
ho aggiunto la cosa anche in c++ è funzia mitico!!!!
grazie!!!
palombaro
16-10-2003, 12:55
come faccio a settare java.library.path ???
palombaro
16-10-2003, 13:00
java.lang.UnsatisfiedLinkError: somma
mi da questa eccezzione. come se non veda la dll
che puo essere?
palombaro
16-10-2003, 13:21
fatto da linea di comando funge perfettamente col jburder9
non trova la libreria dinamica... dove la devo inserire???
A rieccomi (son tornato adesso, altrimenti avrei risposto prima :) )
Allora, in JBuilder (l'ho eliminato, vado a memoria) dovrebbe esserci tra le opzioni del progetto (sul pannello a sinistra, se fai click col pulsante destro sulla cartella del progetto dovrebbe comparire in fondo al popup-menu qualcosa tipo "properties") la possibilità di accedere alle risorse da includere nel progetto.
Cerca, nella finestra che compare, qualcosa tipo "external files" e infila lì il percorso della dll
palombaro
17-10-2003, 13:08
quell opzione non la vedo.... uffi che barba
ti invio la schermatina che mi da magari ti viene in mente!!!
scusa per il disturbo che ti sto dando!!!
No problem, se fosse stato un disturbo non avrei risposto! :)
Prova ad infilare la dll in quel "required libraries".
Altrimenti puoi copiarla nella cartella system di windows, dovrebbe funzionare anche così
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.