Api Java para Terralib5 - wiki DPI

Propaganda
Criação de uma interface Java para TerraLib 5
Fernando Bagnara Mussio 1
Eduardo Laino 1
1
Empresa Brasileira de Aeronáutica S.A - Embraer
Caixa Postal 96 – 12227-901 – São José dos Campos - SP, Brasil
{fernando.bagnara, eduardo.laino}@embraer.com.br
Abstract. This report presents a brief explanation of how to use TerraLib framework, a powerful platform for
GIS development, with the Java programming language. TerraLib code is written in pure C++. The Java
programming language has been widely adopted for its portability and user friendliness. In order to use TerraLib
with other languagens than C++ a binding to the specific language is necessary. A language binding is a
common strategy to allow C/C++ code to be used from another language. It improves software reuse as it avoids
the need for reimplementing the library in several languages. Sometimes it also provides more efficiency due to
the impossibility of implementing certain algorithms (efficiently) in high-level languages like Java. The TerraLib
platform provides bindings for several higher-level languages including Java. In this report is explained how to
add native TerraLib C++ code to a Java program by using an interface for hybrid implementation called Java
Native Interface, or JNI. Java classes were implemented in order to allow Java users to develop GIS applications
in a similar way C++ users should done using TerraLib framework. For the Java classes which add native
TerraLib code it shall be indicated the use of the corresponding dynamic library containing the native code.
Palavras-chave: C++, JNI, GIS, geoprocessamento.
1. Introdução
Este artigo descreve como adicionar implementação nativa da biblioteca TerraLib, escrita
em C++, a programas Java usando a Java Native Interface, ou JNI.
TerraLib 5 é uma plataforma para a construção de aplicativos geográficos que apresenta
classes escritas em C++ com código fonte aberto e distribuída como um software livre. Ela é
compilada em um ambiente multiplataforma, Windows e Linux, e em diferentes compiladores
C++.
A plataforma é desenvolvida seguindo os padrões especificados pela OGC e ISO, tais
como Simple Feature Specification (SFS), Geography Markup Language (GML) e OGC Web
Services. Além disso, TerraLib suporta diferentes tipos de fontes de dados geográficos, como
SGBD (ex; PostGIS, Oracle Spatial and SQLite), arquivos vetoriais e matriciais (ex:
shapefile, kml e geotiff) e serviços WEB (ex: WMS, WFS e WCS). A arquitetura macro da
TerraLib é mostrada na Figura 1.
Figura 1 – Arquitetura Macro da TerraLib
Um aplicativo geográfico que exemplifica a utilização da biblioteca TerraLib é o
TerraView. Na figura 2 é possível observarmos o uso desta biblioteca pelo TerraView.
Java foi desenvolvida por volta de 1990, pouco antes da explosão da Internet. Tendo sido
originalmente concebida para o desenvolvimento de pequenos aplicativos e programas de
controle de aparelhos eletrodomésticos e eletroeletrônicos, Java mostrou-se ideal para ser
usada na rede Internet. Desde então a linguagem de programação Java vem ganhando cada
vez mais adeptos devido à sua simplicidade, riqueza de bibliotecas e portabilidade entre
plataformas e sistemas operacionais. Java é ainda uma linguagem orientada ao objeto,
distribuída, interpretada, robusta, segura, de arquitetura neutra, de alto desempenho,
multithreaded, e dinâmica. Devido a estas características este artigo descreve como utilizar
uma interface de programação híbrida para adicionar implementação nativa da biblioteca
TerraLib, escrita em C++, a programas Java. Utilizou-se para isto uma solução da Sun,
empresa responsável pela criação e atualização da linguagem Java e do seu ambiente de
execução (JVM – Java Virtual Machine), de execução, de dentro do programa Java, de
código nativo, compilado para uma determinada plataforma a partir de código C ou C++. Esta
interface para a programação híbrida é chamada de Java Native Interface, ou JNI.
Ao usar a JNI – Java Native Interface – implementa-se em Java as partes do programa
para as quais esta linguagem melhor se adapte, como, por exemplo, interfaces com o usuário e
com a rede, deixando as partes intensivas em processamento ou recursos locais para serem
implementadas em C ou C++ gerando código nativo. Tomando-se alguns cuidados com o
projeto e a implementação da parte nativa, é de se esperar que os programas resultantes sejam
portáteis, ou seja, recompilando-se a parte nativa pode-se transferir o programa rapidamente
para outras plataformas. Como a JNI faz parte da especificação de Java, a maioria das Java
Virtual Machines (JVM) implementa a mesma, assim como os Java Development Kits (JDK)
provêm suporte apropriado.
Figura 2 – Utilização da TerraLib pelo aplicativo TerraView
2. Metodologia de Trabalho
Considera-se importante delimitar bem as funções de interface entre as linguagens para
um bom projeto JNI. As funções em C ou C++ de contato direto com Java devem traduzir os
dados passados como parâmetros e encaminhá-los às funções da implementação nativa que
realizarão efetivamente o trabalho que se espera. Da mesma forma, devem existir funções que
traduzam de volta para o ambiente Java os resultados produzidos pelas funções nativas
ficando assim identificada o que é interface entre os ambientes e o que é codificação de cada
um. A figura 3 apresenta a arquitetura padrão proposta para a interface via JNI.
Figura 3 – Arquitetura padrão proposta para a interface via JNI.
Para implementação em linguagem Java utilizou-se o ambiente de desenvolvimento do
Eclipse. Do lado Java ao redigir programas que utilizem a JNI, os métodos que serão
implementados em C ou C++ são declarados em qualquer classe como sendo private native,
retornando valores de qualquer tipo, tais como void, int, string, ou mesmo objetos.
Nas classes que contém chamadas para funções nativas, deve ser indicado o uso da
correspondente biblioteca dinâmica TerraLib que contém o código nativo. A forma para se
indicar isso é utilizar o método System.loadLibrary ("nomeDaBiblioteca"). A biblioteca
dinâmica é gerada a partir de código C ou C++ e na compilação em ambiente Windows
Win32 deve ser gerada uma biblioteca .dll.
Para implementação em linguagem C++ utilizou-se o ambiente de desenvolvimento do
Visual Studio C++. Do lado C++, o aplicativo javah pode ser utilizado para facilitar a
implementação do lado nativo dos métodos além de reduzir o número de possíveis erros de
programação. Uma vez definidos na classe Java, pode-se utilizar este aplicativo para gerar um
arquivo .h contendo os protótipos dos métodos da interface na forma C / C++. O módulo de
definição contém as declarações C / C++ necessárias para a compilação dos componentes dos
módulos nativos que interagirão com a JNI.
O arquivo gerado pelo javah deve incluir dois arquivos localizados no pacote do JDK.
Estes arquivos de inclusão são adicionados como se fossem arquivos do compilador usando
um comando #include <nome-do-arquivo>, sem qualquer indicação de onde estão os arquivos
de inclusão. O programador deve configurar corretamente o seu ambiente de desenvolvimento
C ou C++ de modo que os arquivos de inclusão sejam encontrados durante a compilação.
Para adquirir, atribuir e devolver valores para um objeto Java, é necessário usar o pacote
de funções padrão C ou C++ que lidam com os elementos Java passados para a
implementação. Parâmetros primitivos (int, float, etc.) podem ser utilizados sem necessidade
de qualquer tradução e podem ser retornados da mesma forma. No caso de strings, no entanto,
é prudente lembrar-se de liberar a memória ocupada pelo string antes de retornar.
2.1 Usando javah para gerar o .h
Se o programador optar por utilizar o javah para gerar o .h com as definições das funções
nativas correspondentes aos métodos definidos na classe Java, o programador deve primeiro
compilar a classe. Serão gerados diversos arquivos .class, um para cada classe contida no
arquivo .java compilado:
javac arquivo.java
Após isto o programador pode gerar o .h:
javah –jni Nome-Da-Classe
Será gerado o arquivo .h que obedece a estrutura mostrada na figura 4. O arquivo .h inclui
o arquivo jni.h do sistema, localizado no diretório include do pacote JDK.
Javah insere comentários sobre cada método nativo criado, logo antes de seus protótipos. Estes
comentários contém o nome da classe, o nome do método em Java e as classes dos objetos
usados como parâmetros ao método.
A definição do protótipo da função nativa que implementa o método sempre começa com
JNIEXPORT, seguido do tipo de retorno do método, seguido de JNICALL, e finalmente o nome da
função, composto pela concatenação: Java_ + <nome da classe que contém o método>_ + <nome
do método>. O tipo de retorno é um dos fornecidos por JNI: jboolean, jbyte, jchar, jshort,
jint, jlong, jfloat, jdouble ou void.
#include <jni.h>
#ifndef _Included_nomeClasse
#define _Included_nomeClasse
#ifdef __cplusplus
extern "C" {
#endif
/*
* Comentários sobre o método nativo aqui...
*/
JNIEXPORT tipoRetorno JNICALL Java_nomeClasse_nomeMétodo
(JNIEnv *, jobject[, tipo-parâmetro[...]]);
...
#ifdef __cplusplus
}
#endif
Figura 4 – Estrutura do arquivo .h gerado pelo javah
No caso dos parâmetros passados à função, JNIEnv constitui um portal de comunicação entre o
lado nativo e o lado Java. O primeiro jobject também sempre é passado: ele é um ponteiro para o
objeto que chamou este método nativo. Depois há um tipo para cada parâmetro definido para o
método.
2.2 Regras do lado C++
Ao desenvolver programas que interagem através da JNI devem ser observadas regras do
lado do código nativo. Somente objetos visíveis nos parâmetros passados às funções de
interface da implementação nativa podem ser acessados por estas funções.
Se um parâmetro primitivo for passado (int, por exemplo), este parâmetro será acessado
diretamente sem ser necessária a utilização de uma função JNI para traduzi-lo. O programador
deve ter apenas o cuidado de saber lidar com o tamanho em bits deste tipo primitivo e utilizar
os tipos nativos certos. Vale lembrar que String não é um tipo primitivo.
Se o parâmetro passado for um objeto, então qualquer operação que o envolva deverá ser
feita por via de uma função JNI. Desta forma, o ambiente Java permanece razoavelmente
encapsulado e sua estrutura interna é irrelevante para a implementação nativa.
Um elemento de um objeto não é acessado diretamente, sendo separado em duas etapas: adquirir
o identificador deste elemento (determinando a classe) e adquirir o valor através deste identificador.
Para adquirir a classe a que o objeto pertence, utiliza-se a seguinte função (notação C):
jclass GetObjectClass( JNIEnv* pEnv, jobject obj );
onde:
pEnv é o ponteiro do tipo JNIEnv * recebido pela função nativa
obj é o objeto do qual se deseja determinar a classe.
Para interagir com um atributo da classe é necessário primeiro obter o seu identificador. Com este
identificador pode-se então interagir com o atributo. Para adquirir um identificador, quando se
conhece a classe do objeto, utiliza-se a seguinte função se o elemento não for estático:
jfieldID GetFieldID( JNIEnv* pEnv, jclass classe, const char* pNome, const char*
pTipo );
onde:
pEnv é o ponteiro do tipo JNIEnv * adquirido pela função nativa,
classe é a classe obtida com a função anterior,
pNome é umstring contendo o nome do elemento a ser identificado e
pTipo é umstring que identifica o tipo deste elemento,
O valor deste elemento pode então ser adquirido visto que o identificador já é conhecido:
tipoNativo GetTipoField( JNIEnv* pEnv, jobject obj, jfieldID id );
onde:
pEnv e obj foram adquiridos pela função nativa, e
id foi adquirido pela função anterior.
tipoNativo é um dos diversos tipos primitivos de C ou C++ (int, por exemplo).
Tipo é o tipo primitivo do lado Java.
Existem funções GettipoField ou GetStatictipoField para cada tipo conhecido por Java. O tema
Tipo no nome das funções identifica o tipo do campo a ser acessado.
2.2.1 Regras do lado C++ para Strings
Uma string Java pode ser adquirida como parâmetro para a função nativa ou como parte
de um objeto passado como parâmetro. Para o caso da string ser parte de um objeto, ela deve
antes ser identificada também.
Java usa strings no formato Unicode. Ao adquirir valores de strings passadas por Java, a
implementação nativa pode adquirir cópias traduzidas para ASCII ou cópias em Unicode
mesmo. JNI fornece funções capazes de lidar com ambos os casos ASCII e Unicode.
Algumas funções fornecidas por JNI:
Para saber o comprimento de uma string Java retornando o número de caracteres Unicode
de string:
jsize GetStringLength( JNIEnv* pEnv, jstring string);
Para saber o comprimento de uma string Java retornando o número de caracteres UTF-8
(compatível com ASCII):
jsize GetStringUTFLength( JNIEnv* pEnv, jstring string);
Para adquirir uma cópia de uma string Java, em Unicode:
const jchar* GetStringChars( JNIEnv* pEnv, jstring string, jboolean*
pIsCopy );
Para adquirir uma cópia de uma string Java, no formato UTF-8:
const char* GetStringUTFChars( JNIEnv* pEnv, jstring string, jboolean*
pIsCopy );
Para liberar a cópia adquirida deverá utilizar uma das funções seguintes de acordo com o
tipo de cópia:
void ReleaseStringChars( JNIEnv* pEnv, jstring string, const jchar* pUniStr
);
ou
void ReleaseStringUTFChars( JNIEnv* pEnv, jstring string, const char*
pStr );
Para criação de strings Java pelo lado nativo baseando-se em variáveis string nativas:
jstring NewString( JNIEnv* pEnv, const jchar* pUniStr, jsize
comprimento );
jstring NewStringUTF( JNIEnv* pEnv, const char* pStr );
2.2.2 Regras do lado C++ para vetores
O conjunto de funções JNI para acesso a vetores apresenta funções para acesso completo
a vetores de tipo primitivo, acesso parcial a vetores de tipo primitivo e acesso a elementos de
vetores de objetos.
Se o vetor é de elementos de tipos primitivos (int, por exemplo), o programador pode
optar por adquirir uma cópia completa do vetor ou uma cópia parcial, dependendo do
desempenho que desejado.
As funções de acesso a vetores de tipo primitivo são:
tipoNativo* GetTipoArrayElements( JNIEnv* pEnv,TipoArray vetor,
jboolean* pIsCopy );
onde:
tipoNativo e Tipo são equivalentes ao tipo primitivo dos elementos do vetor para
o lado nativo e para o lado Java. Para o caso da definição do vetor, o tipo primitivo é seguido
de Array.
Para se adquirir uma cópia completa do vetor e liberá-la, as modificações no vetor
copiado só terão garantia de serem espelhadas para o vetor Java ao executar esta função:
void ReleaseTipoArrayElements( JNIEnv* pEnv, tipoArray vetor,
tipoNativo* copia, jint opcao );
onde
Tipo e tipoNativo são os tipos primitivos,
copia é a cópia do vetor adquirida com a função descrita no início deste tópico e
opção é recomendada ser 0 (zero), isto é, copia o conteúdo de copia e libera o espaço alocado
para copia.
Para tratar vetores de objetos, é necessário adquirir cada elemento por vez com as
funções de acesso a vetores de objetos:
jobject GetObjectArrayElement( JNIEnv* pEnv, jobjectArray vetor, jsize
indice );
void SetObjectArrayElement( JNIEnv* pEnv, jobjectArray vetor, jsize
indice, jobject valor );
onde:
indice é o índice do elemento a ser manipulado e valor o valor a ser atribuído a
ele.
Para adquirir o número de elementos de um vetor Java, utiliza-se a função abaixo que
serve para qualquer vetor Java, seja ele primitivo ou de objetos:
jsize GetArrayLength( JNIEnv* pEnv, jarray vetor );
Para criar um vetor Java pelo lado nativo utiliza-se uma das funções:
tipoArray NewTipoArray( JNIEnvv* pEnv, jsize tamanho );
jarray NewObjectArray( JNIEnv* pEnv, jsize tamanho, jclass
classeElementos, jobject valorInicial );
onde
tamanho é o número de elementos do vetor,
classeElementos é a classe a que os elementos pertencem e
valorInicial é o valor inicial dos elementos até que sejam alterados pelo
programa.
3. Resultados e Discussão
O diagrama de classes em C++ da biblioteca TerraLib é mostrado na figura abaixo:
Figura 5 – Diagrama de classes C++ da TerraLib.
3.1 Diagrama das classes Java para TerraLib
O diagrama das classes Java que acessam a biblioteca TerraLib está descrito na figura 6.
As classes Java implementam métodos utilizados pela interface JNI para adicionar
implementação nativa da biblioteca TerraLib. Conforme já explicado anteriormente estes
métodos em Java devem ser declarados como sendo private native. Para cada classe Java com
método nativo foi criada uma classe C++ correspondente com a implementação nativa para a
biblioteca TerraLib.
Figura 6 – Diagrama de classes Java com implementação para objetos TerraLib.
Para as classes Java foram escolhidos nomes análogos aos componentes da plataforma
TerraLib de maneira a facilitar a compreensão do programador para a implementação.
Na figura 7 podemos observar o método stop da classe Plataform no arquivo
Plataform.java com o método nativo e na figura 8 a estrutura do arquivo Platform.h gerado
por javah seguindo as regras da interface JNI. A figura 9 apresenta a implementação
correspondente do método stop na classe Platform em C++ .
package te;
public final class Platform {
private Platform() {
}
public static native void start();
public static native void stop();
static {
System.load("TerraLib_binding_java_d.dll");
}
}
Figura 7 – Arquivo Platform.java: Método stop da classe Plataform em Java
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class te_platform_Platform */
#ifndef _Included_te_platform_Platform
#define _Included_te_platform_Platform
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:
te_Platform
* Method:
stop
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_te_Platform_stop
(JNIEnv *, jclass);
JNIEXPORT jint JNICALL JNI_OnLoad
(JavaVM*, void*);
JNIEXPORT void JNICALL JNI_OnUnLoad
(JavaVM*, void*);
#ifdef __cplusplus
}
#endif
#endif
Figura 8 – Arquivo Plataform.h: Estrutura gerada por javah
void JNICALL Java_te_Platform_stop(JNIEnv* env, jclass /*clazz*/)
{
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_envelopeClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_geomClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_ptClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_transactorClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_datasetClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_catalogClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_datasourceClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_propertyClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_complexClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_datasettypeClazz);
env->DeleteWeakGlobalRef(te::java::ClassCache::sm_canvasClazz);
te::plugin::Platform::finalize();
te::qt::widgets::Platform::finalize();
te::da::Platform::finalize();
te::gm::Platform::finalize();
te::common::Platform::finalize();
delete qtapp;
qtapp = 0;
}
Figura 9 – Método stop da classe Plataform em C++
3.2 Classes genéricas Plataform e TerraLib4J
O diagrama das classes Platform e TerraLib4J é apresentado na Figura 10. A classe
TerraLib4J é uma classe genérica que possui um atributo para armazenar um descritor, um
handle JNI passado pelas classes filhas.
A classe Platform é utilizada para iniciar e encerrar a biblioteca TerraLib com os
respectivos métodos start e stop.
Figura 10 – Métodos das classes Platform e TerraLib4A
3.3 Grupo de classes acesso aos dados
O diagrama das classes pertencentes ao grupo de classes de acesso aos dados é
apresentado na Figura 11, na Figura 12 e na Figura 13.
Na biblioteca TerraLib, uma fonte de dados (data source) pode ser um provedor de dados
geográficos tanto quanto de dados descritivos. É caracterizdo por um conjunto de parâmetros
que podem ser usados para configurar um canal de acesso para o repositório
(DataSourceInfo).
Cada fonte de dado (data source) tem um catálogo de dados, representado por um objeto
DataSourceCatalog. Este catálogo contem informações sobre os conjuntos de dados (data
sets) armazenados na fonte de dados e de como estão organizados.
A lista das fontes de dados suportadas:
PostGIS
Oracle Spatial
SQLite
GDAL (driver para acesso a diversos formatos de arquivos de imagem)
OGR driver para acesso a diversos formatos de arquivos vetoriais)
Figura 11 – Métodos das classes DataSourceTransactor e DataSetType
Figura 12 – Métodos das classes DataSource e DataSet
Figura 13 – Métodos das classes DataSourceCatalog, DataSourceFactory, PropertyType
e ComplexType
3.4 Modelo de Geometrias
O diagrama das classes pertencentes ao grupo de classes filhas de Geometry é apresentado
na Figura 14.
Na TerraLib os dados geográficos são agregados em layers. Layers são formados por
conjuntos de objetos, onde cada objeto possui uma identificação única, um conjunto de
atributos descritivos e uma representação geométrica.
A classe Geometry representa a classe base análoga em TerraLib da qual derivam todas as
geometrias de TerraLib.
Cada geometria possui uma identificação única, a referência ao seu menor retângulo
envolvente e a identificação do objeto geográfico que representa.
Um determinado tipo de geometria é a classe Points que possui sua classe análoga em
TerraLib referente a pontos.
Figura 14 – Métodos do Grupo de classes Geometry
3.5 Exemplo Java
A figura 15 apresenta um exemplo escrito em Java de utilização das classes Java para
acessar código nativo da biblioteca TerraLib. A biblioteca é carregada dinamicamente pela
classe Platform através do comando System.load(“...TerraLib_binding_java_d.dll”) visto na
Figura 7.
No exemplo abaixo a biblioteca TerraLib é iniciada pelo comando te.Platform.start () e ao
final é encerrada com te.Platform.stop (). A partir de sua iniciação é possível utilizar as
classes Java para abrir e manipular fontes de dados vetoriais como feito no exemplo abaixo
através dos comandos para instanciar objetos DataSource, DataSourceTransactor e DataSet
ou realizar comandos estáticos a partir das classes como DataSourceFactory.
import te.gm.Envelope;
import te.gm.GeometryFactory;
import te.gm.Point;
public final class DataAccessExample {
public static void main(String args[])
throws java.io.IOException
{
// Iniciacao da biblioteca TerraLib
te.Platform.start();
// Construcao e abertura de um DataSource
te.da.DataSource datasource =
te.da.DataSourceFactory.make("DataSource=OGR&C:\\ProjetoInpe\\TerraLib_fernando_b\\data\\shp\\coun
try.shp");
datasource.open();
// Manipulacao de um datset do DataSource
te.da.DataSourceTransactor transactor = datasource.getTransactor();
te.da.DataSet dataset = transactor.getDataSet("country");
while(dataset.moveNext()){
System.out.println("Field 0:" + dataset.getAsString(0));
}
// Encerramento da biblioteca TerraLib
te.Platform.stop();
}
}
Figura 15 – Programa exemplo das classes em Java
3.6 Exemplo de aplicativo para leitura e apresentação gráfica de arquivo vetorial
O aplicativo mostrado na Figura 16 foi desenvolvido como exemplo de leitura de datasets
vetoriais a partir das classes Java que utilizam código C++ nativo da biblioteca TerraLib.
A seguinte seqüência é possível realizar:
1. Abrir uma fonte de dados (“DataSource”), no caso um arquivo “shape”;
2. Carregar “DataSourceCatalog” para obter informações sobre o conteúdo do
“DataSource”, como o número de “DataSet”s disponíveis e qual deles contém
dados geométricos;
3. Abrir o “DataSet” que contém dados geométricos;
4. Ler os dados geométircos do “DataSet”;
5. Criar um objeto “Canvas”, uma tela para criação de imagem, considerando
largura, altura e escala mais adequadas para o desenho;
6. Desenhar as geometrias sobre o “Canvas”
7. Gerar uma imagem a partir da tela criada e apresentar.
Figura 16 – Aplicativo para abertura de datasets vetoriais
4. Conclusões
Este artigo apresentou os conceitos e técnicas básicas para o desenvolvimento de uma
interface Java para a TerraLib5 que são aplicações híbridas envolvendo Java a interface nativa
Java (JNI) e biblioteca dinâmica nativa criadas a partir de código C++ para acesso a biblioteca
TerraLib.
Além de apresentarmos as técnicas básicas para implementar tais aplicações, foram
apresentados, ainda alguns exemplos que ilustram as diferentes modalidades de interface.
Agradecimentos
Gostaríamos de agradecer a Gilberto Ribeiro de Queiroz e Karine Reis Ferreira,
profissionais do Inpe que participam ativamente no desenvolvimento do projeto da biblioteca
TerraLib e que nos orientaram neste trabalho.
Referências Bibliográficas
Felipe Carasso, Arndt von Staa. Utilizando JNI para Adicionar Implementação Nativa C
ou C++ a Programas JAVA. 2002. 35 p. (ISSN 0103-9741). Dissertação (Monografias em
Ciência da Computação) – Pontifíca Universidade Católica do Rio de Janeiro – Rio de
Janeiro .2002.
INPE-DPI. O aplicativo TerraView. Disponível em: <http://www.dpi.inpe.br/terraview>.
Acesso em: Junho 2010.
Download