Segue
portanto o código do arquivo calcjna.c
:
#include "stdio.h"
#include "strings.h"#include "calcjna.h"
int calcular(char* op, int arg1, int arg2) {
int calc = -1;
if(strcmp(op,"soma") == 0) {
calc
= arg1 + arg2;}
else
if(strcmp(op,"subtracao")
== 0) {
calc = arg1 - arg2;}
else {
printf("Operacao %s invalida\n",
op);
return calc;
}
printf("Operacao de %s. Executada com sucesso!\n", op);
return calc;
}
Não
podemos esquecer de criar o arquivo Header. Segue o código do arquivo calcjna.h :
int calcular(char* op, int arg1, int arg2);
Agora
para gerarmos a biblioteca compartilhada:
gcc
calcjna.c -shared -I. -o libcalcjna.so
Pronto,
criamos nossa biblioteca nativa (Certifique-se de que o nome do objeto criado
inicia com lib). Agora vem a parte
interessante que é a comunicação da linguagem Java com o código nativo via JNA. Para fazer isso devemos criar
uma interface em Java que fará o mapeamento dos tipos. O mapeamento de tipos
compatíveis pode ser encontrado aqui sob a sigla "Default Type Mappings".
Segue
o código de nossa interface ICalcJNA.java :
import
com.sun.jna.Library;
public interface ICalcJNA extends Library {
public int calcular(String operacao, int elemento1, int elemento2);
}
Veja
que mapeamos o tipo char* para o tipo String do Java, bem como o tipo int que é
o mesmo em ambas linguagens.
Estamos
quase no fim, só falta criar o arquivo responsável pela carga da biblioteca,
que terá o nome de CalcJNA.java :
import com.sun.jna.Native;
public class CalcJNA {
public static void main(String args[]) {
ICalcJNA
calc =
(ICalcJNA)
Native.loadLibrary("calcjna", ICalcJNA.class);
int i = calc.calcular("soma", 10,
5);
System.out.println(i); i = calc.calcular("subtracao", 10,
5); System.out.println(i); i = calc.calcular("divisao", 10, 5);
System.out.println(i);
}
}
OBS Linux
Devemos informar somente o nome da biblioteca sem o
inicio lib e sem o final .so.
A
partir de agora é só compilar e executar o código, caso você não tenha gravado
o arquivo jna.jar em algum diretório que o Java o encontre, deveremos informar
explicitamente ao compilador onde ele deve buscar as classes que utilizamos, no
meu caso o arquivo JAR está no mesmo diretório que estão todos os outros
arquivos que criamos aqui. Portanto, vamos compilar:
java -cp
.:./jna.jar CalcJNA
O
resultado deveria ser esse:
Operacao
de soma. Executada com sucesso!
15
Operacao
de subtracao. Executada com sucesso!
5
Operacao
divisao invalida
-1
Integrando com Windows (DLL)
O objetivo aqui será obter a data e a hora do
sistema através de uma biblioteca nativa do sistema operacional, vamos obter
essas informações através da DLL KERNEL32.DLL que fica localizada no diretório
de instalação do Windows e na subpasta SYSTEM32.
1 Passo: Criar nossa interface que é a única parte burocrática na
utilização do JNA:
import
com.sun.jna.win32.StdCallLibrary;
public interface IKernel32 extends
StdCallLibrary {
void GetSystemTime(DataHoraSistema result);
}
Podemos notar que existe uma diferença aqui nessa interface, aqui
ela não é herança de Library, mas sim de StdCallLibrary. Isso porque essa DLL
usa a convenção __stdcall de chamada de métodos, porém na maioria dos casos as
bibliotecas serão herança de Library mesmo.
Definimos no código acima a
interface de acesso ao método GetSystemTime
que recebe um parâmetro do tipo Structure pois o método nativo recebe como
parâmetro uma estrutura nativa e que será populada com informações de data e
hora do sistema.
Para isso teremos que definir uma
classe Java que será herança da classe Structure.
Isso só é necessário quando métodos nativos recebem ou devolvem parâmetros do
tipo de estruturas nativas. Lembrando que a DLL em questão possui vários outros
métodos, mas como utilizaremos apenas um, definimos apenas ele. Salve esse
arquivo como IKernel32.java.
2 Passo: Vamos então mapear nossa estrutura Java para trocarmos
informações com a biblioteca nativa através dessa estrutura:
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
Criamos aqui um tipo que é herança
de Structure e mapeamos os tipos para short que é o equivalente ao tipo WORD do
Windows. Para isso utilizamos a tabela de mapeamento que encontramos aqui como
citado no primeiro artigo. Salve como DataHoraSistema.java.
3 Passo:
Implemente a interface IKernel32:
import com.sun.jna.Native;
public class Kernel32JNA {
public static void main(String args[]) {
IKernel32 lib =
(IKernel32)
Native.loadLibrary("kernel32", IKernel32.class);
DataHoraSistema time = new DataHoraSistema();
lib.GetSystemTime(time);
System.out.println("Data: " + time.wDay +
"/" +
time.wMonth +
"/" +
time.wYear);
System.out.println("Hora: " +
time.wHour +
":" +
time.wMinute);
}
}
No código acima apenas obtemos uma
instância da biblioteca KERNEL32.DLL através do método loadLibrary do JNA que é quem faz toda a mágica e, a partir daí,
trabalhamos com os tipos e métodos fornecidos pela própria biblioteca nativa e
que mapeamos na classe DataHoraSistema do Java.
A partir daí é só a gente compilar:
javac -cp .;jna.jar Kernel32JNA.java
E executar:
java -cp .;jna.jar Kernel32JNA
Resultado:
Data: 5/2/2008
Hora: 13:26
Nenhum comentário:
Postar um comentário