Ajuda com o Hello World do JNI [Resolvido]

14 respostas
oddy.silva

Bom dia pessoal. Eu tô precisando de um tutorial de JNI, pode ser um e-book, artigo acadêmico ou afins. Antes que alguém pergunte, aqui na empresa tem um proxy e eu não posso fazer downloads, logo, a busca no Google não adianta nada nesse caso.
Se alguém puder enviar por email pra mim, agradeço.

14 Respostas

T

http://nano.xerox.com/mtvjug/jni.ppt
http://java.sun.com/docs/books/jni/download/jni.pdf

oddy.silva

Bacana, baixei as apostilas e tal, mas fui fazer o meu Hello World! e deu pau.
Gostaria de saber se alguém pode me ajudar, já que estou aprendendo o JNI agora.
Passo a passo vou descrever e mostrar o que fiz.

1 - Código em java

class HelloWorld {
    private native void print();
    public static void main(String[] args) {
        new HelloWorld().print();
    }
    static {
        System.loadLibrary("HelloWorld");
    }
}

2 - Gerei o .class

javac HelloWorld

3 - Gerei o .h

javah -jni HelloWorld.class

4 - Editei meu arquivo em C

#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
    printf("Hello World!\n");
    return;
}

Daí digitei no meu terminal do Linux, para gerar o .so:

cc -G -I/opt/jdk1.6.0_1/include -I/opt/jdk1.6.0_1/include/linux HelloWorld.c -o libHelloWorld.so

Daí recebi a seguinte mensagem de erro:

HelloWorld.c:1:17: error: jni.h: Arquivo ou diretório inexistente
In file included from HelloWorld.c:3:
HelloWorld.h:15: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?void?
HelloWorld.c:5: error: expected ?=?, ?,?, ?;?, ?asm? or ?__attribute__? before ?void?

Eu gerei um .so pq estou no Linux. Parece que está dando pau no Import do jni, no meu arquivo em C. Alguém tem alguma idéia do que está acontecendo?

T

Hum… você tem um arquivo jni.h nesses diretórios especificados com -I ? tem certeza que é /opt/jdk1.6.0_1 não /opt/jdk1.6.0_01 ?

oddy.silva

Thingol, tentei aqui trocar de 1 para 01 no final, mas continua a mesma coisa viu. O que eu fiquei pensando é o seguinte: no Windows, as dll fican na Win32, mas onde será que ficam os arquivos de extensão .so, no Linux? Talvez esse seja o principal problema, pq realmente ele não encontra o jni.

T

Primeiro resolva o erro de compilação, que diz claramente que o compilador não conseguiu achar o arquivo jni.h nos diretórios especificados com a opção -I. O arquivo jni.h é necessário para poder definir algumas coisas usadas por HelloWorld.h, portanto você não pode omiti-lo.

oddy.silva

Eu vou dar um

find / -name jni.h

no Linux, daí ele vai me dizer onde está esse arquivo. Se eu não conseguir, eu volto aqui e a gente vê o que faz.

oddy.silva

Thingol, o comando retornou o caminho completo para o arquivo:

/opt/jdk1.6.0_11/include/jni.h

era o JDK 6 Update 11, e não o 01, como eu havia digitado.

Agora eu digito o seguinte:

cc -G -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux HelloWorld.c -o libHelloWorld.so

Mas ele retorna o seguinte erro:

(.text+0x18): undefined reference to `main'
collect2: ld returned 1 exit status

O que pode ser agora? Eu vou dando uma olhada no código enquanto isso.

T

Para compilar um .so os parâmetros não são suficientes. Você usou apenas -o arquivo.so; isso faz com que o linker tente achar um “main”, o que obviamente não é o que você quer.

O comando, aparentemente, é o que você pode achar nesta página:

http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html

# obviamente o comando a seguir é todo em uma linha
gcc  -o libnativelib.so -shared -Wl,-soname,libnative.so  
     -I/export/home/jdk1.2/include 
     -I/export/home/jdk1.2/include/linux nativelib.c  
     -static -lc

(Não sabia que existia esse treinamento da Sun. Olhe os outros capítulos.)

oddy.silva

Tentei da maneira abaixo:

gcc -o libHelloWorld.so -shared -Wl, -HelloWorld, libHelloWorld.so -I/export/opt/jdk1.6.0_11/include -I/export/opt/jdk1.6.0_11/include/linux HelloWorld.so

Mas recebi a msgm:

gcc: libHelloWorld.so: Arquivo ou diretório inexistente
gcc: HelloWorld.so: Arquivo ou diretório inexistente
gcc: unrecognized option '-HelloWorld.so,'
T

Hum hum hum… você viu que o Linux tem também seus segredos. No seu caso, você pôs espaços depois de cada vírgula; não é para pô-los. O comando é realmente “-Wl,-soname,libSeuArquivo.so”, sem os espaços. “man gcc” para as opções.

oddy.silva

Então cara, digitei assim:

gcc -o libHelloWorld.so -shared -Wl,-HelloWorld,libHelloWorld.so -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux HelloWorld.c -static -lc

E agora obtive:

/usr/bin/ld: unrecognized option '-HelloWorld'
/usr/bin/ld: use the --help option for usage information
collect2: ld returned 1 exit status
T

Use o “man gcc” ou “man ld”, não sei qual deles tem a opção “-soname”.
A opção tem o nome de “-soname” mesmo; não é algo que você tem de substituir pelo nome do seu arquivo .so.

oddy.silva

Bom, onde tinha -HelloWorld, eu troquei para -soname. Agora parece que deu certo.
Ficou assim

gcc -o libHelloWorld.so -shared -Wl,-soname,libHelloWorld.so -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux
oddy.silva

Funciounou! :cry:

Thingol,obrigado pela paciência e disposição. Mais uma vez, muitíssimo obrigado. Bom trabalho pra você. Vlw!

Criado 13 de abril de 2009
Ultima resposta 13 de abr. de 2009
Respostas 14
Participantes 2