Hospedagem Profissional

Hospedagem Profissional
Clique aqui e ganhe US$ 10,00 para testar durante 1 mês a melhor hospedagem: Digital Ocean!

quinta-feira, 12 de fevereiro de 2009

Chamando métodos nativos (.dll/.so/…) em java sem JNI

Uma das coisas mais chatas em java é que quando é necessário utilizar algum método nativo de qualquer biblioteca de qualquer sistema operacional, é necessário criar uma classe stub com métodos declarados como native, depois gerar um .h com o comando javah e implementar aquele método nativo com o compilador C de sua escolha, mesmo que isto seja apenas um proxy para alguma função de alguma DLL que já existe com exatamente os mesmos parametros, certo? errado!
Isto só era desta forma até criarem o projeto Java Native Access (JNA)
Na página do projeto existem alguns exemplos de chamadas a bibliotecas padrão do sistema operacional (tanto linux quando windows), mas eu não estava muito feliz com isto, imaginem se eu ja desenvolvi uma DLL/SO ou pior ainda, eu preciso chamar alguns métodos de uma DLL fornecida por alguem? e ai preciso ainda de toda aquela parafernalha do JNI?
Não precisa mais, e só para comprovar eu criei este exemplo simples!

Comecemos criando um biblioteca (a minha máquina é linux, por tanto vou criar um .so podem fazer o mesmo teste em um windows por ai se quiserem, mas por enquanto eu ja estou bastante feliz :D )
arquivo testejna.h

#ifndef testejna_H
#define testejna_H
void librarymethod(char* whatToSay);
#endif



vamos implementar isto no arquivo testejna.c




#include 
#include
#include "testejna.h"

void librarymethod(char* whatToSay)
{
printf("Java Rocks, I'm Calling this without JNI and telling the C code to Say: %s !\n",whatToSay);
}



tudo pronto, mandei o kdevelop compilar isto para mim, e ele criou o arquivo libtestejna.so, agora a nossa tarefa é chamar a função librarymethod desta biblioteca dinâmica (.so no linux, .dll no windows) a partir do nosso código java! preparem-se para passar trabalho :D


Só brincadeira, criei um projeto java novo no IntelliJ IDEA e adicionei o arquivo jna.jar no classpath (pode ser baixado do site do projeto)


Criei uma interface com a declaração do método que quero chamar, a idéia é uma interface possuir todos os métodos do .so/.dll que a aplicação for utilizar.




package testejna;

import com.sun.jna.Library;

public interface MySharedLibrary extends Library {
public void librarymethod(String whatToSay);
}



Como podem ver, a única exigencia é que esta interface extenda com.sun.jna.Library, e esta tudo pronto, podemos agora utilizar a biblioteca dinâmica ja criada, e sem toda aquela encheção de saco do JNI!

Mas como?


Assim:




package testejna;

import com.sun.jna.Native;

public class TesteJNA {
public static void main(String args[]){
MySharedLibrary lib = (MySharedLibrary) Native.loadLibrary("testejna", MySharedLibrary.class);
lib.librarymethod("Java Rocks");
}
}



E executando o programa extremamente complexo em java que foi criado é impresso no console:




Java Rocks, I'm Calling this without JNI and telling the C code to Say: Java Rocks !



A idéia básica é que o método loadLibrary da classe com.sun.jna.Native cria um proxy para a interface que definimos, e cada método chamado deste próxy será direcionado para a biblioteca nativa.



O JNA ja tem suporte para diversas plataformas, olhando dentro do arquivo jna.jar, eles ja possuem suporte para:




  • darwin (Mac OS X)


  • freebsd-i386


  • linux-amd64


  • linux-i386


  • sunos-sparc


  • sunos-sparcv9


  • sunos-x86


  • win32


  • win32-x86



Ou seja, a grande maior parte dos sistemas utilizados por ai.

O que acontece é que eles possuem 1 biblioteca nativa para cada um destes sistemas operacionais que funciona de proxy para qualquer outra biblioteca do mesmo.



Eu achei o projeto espetacular, e a partir de hoje, não precisamos mais entrar em desespero sempre que for necessário chamar algum método nativo de alguma biblioteca proprietária (o pessoal que precisa trabalhar com impressoras fiscais que deve ficar bastante feliz :D )



Por Urubatan

em http://www.urubatan.com.br/chamando-metodos-nativos-dllso-em-java-sem-jni/