Mistureba: C/C++ e Java

Suponha que você tenha uma library,  bem “azeitada”, totalmente feita em C/C++. Vocẽ deseja usá-la em uma aplicação feita em Java… Não, não é impossível! De fato, existe uma especificação para isso chamada JNI (java Native Interface), porque os desenvolvedores do java sabem que código interpretado pode ser um pé-no-saco…

Eis um exemplo simples de como usar a JNI: O bom e velho HelloWorld. A primeira coisa a fazer é criar a classe com a chamada que você quer fazer para a sua library:

public class HelloWorld
{
  /* Esse será o nosso "método nativo". */
  private native void print();

  static {
    System.loadLibrary("HelloWorld"); // carrega libHelloWorld.so
  }

  public static void main(String[] args) {
    new HelloWorld().print();
  }
}

Compile a classe acima com “javac HelloWorld.java” e obtenha o HelloWorld.class.

Uma vez feito isso, temos que gerar o arquivo .h para que nosso programinha em C/C++ saiba qual é a assinatura da função print declarada na classe HelloWorld:

$ javah -jni HelloWorld.class -o HelloWorld.h

Você deve obter um arquivo HelloWorld.h assim:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

#ifndef __HelloWorld__
#define __HelloWorld__

#ifdef __cplusplus
extern "C"
{
#endif

JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *env, jobject);

#ifdef __cplusplus
}
#endif

#endif /* __HelloWorld__ */

Note que a função em HelloWorld.h é nomeada como “Java_<classe>_<método>”. Agora é só criar o arquivo .c:

/* libHelloWorld.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;
}

Note que “env” é o ponteiro para um objeto que contém diversas informações e funções do ambiente de runtime da JVM. E o parâmetro “obj” é, provavelmente, o ponteiro para o objeto chamador.

Se a sua função tiver mais parâmetros eles serão adicionados na lista de parâmetros da função, na assinatura da função em C, pelo utilitário javah.

Agora é só compilar o nosso código e testá-lo com:

$ gcc -shared libHelloWorld.c -o libHelloWorld.so
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
$ java HelloWorld
Hello World!
$

A adição do diretório onde libHelloWorld.so encontra-se, na variável LD_LIBRARY_PATH, é necessária para a JVM encontrar nossa library. Se não colocarmos o shared object num diretório listado em LD_LIBRARY_PATH obteremos o seguinte erro:

$ java HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1681)
	at java.lang.Runtime.loadLibrary0(Runtime.java:840)
	at java.lang.System.loadLibrary(System.java:1047)
	at HelloWorld.<clinit>(HelloWorld.java:11)
Could not find the main class: HelloWorld. Program will exit.

Existem muito outros recursos na JNI. Eis um PDF de um livro explicando como usá-la (clique aqui para baixar).

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s