Artigo no estilo: Curso

De que se trata o artigo:

Vamos descer alguns degraus das costumeiras linguagens de alto-nível da JVM, e examinar a programação com código nativo, integrado à JVM através da JNI – ou da JNA, alternativa mais moderna e muito mais produtiva.


Para que serve:

Com o avanço do desempenho das JVMs, hoje em dia é raro precisarmos de código nativo por motivo de desempenho. Mas isso ainda acontece, embora a decisão já não seja tão simples. Com maior frequência, precisamos de código nativo por outros motivos, como acesso a bibliotecas legadas ou a serviços do sistema operacional que não possuem API Java equivalente.


Em que situação o tema é útil:

Neste artigo, guiaremos o leitor pelo suporte do Eclipse e NetBeans para desenvolvimento nativo, através dos seus plug-ins para C/C++. Daremos também uma introdução atualizada à JNI (Java Native Interface), e também à JNA, uma biblioteca open source que torna a programação JNI muito mais fácil, segura e produtiva. Também examinaremos os custos de desempenho e outros aspectos do acesso ao código nativo.

Este artigo desvia um pouco da nossa linguagem favorita, adentrando pelo mundo do C e C++ ou, como diria qualquer fã do Java: afundando o pé na lama do C e C++. Afinal, estas linguagens precedem Java, e foram substituídas por Java (e outras linguagens modernas) para muitos projetos, por bons motivos: Java é mais portável, produtiva e segura, entre várias outras qualidades.

Mas nenhuma linguagem ou plataforma é ideal para tudo; C/C++ continuam sendo utilizadas para muitos tipos de desenvolvimento. Mesmo hoje, não é raro que um desenvolvedor, ou uma empresa que trabalha primariamente com Java, precise de uma “pitada” de C/C++, por vários motivos:

• Dar manutenção em algum legado;

• Fazer integração entre projetos Java com alguma biblioteca ou legado C/C++;

• Acessar APIs e recursos da plataforma nativa, que talvez não tenham API Java correspondente;

• Otimização: bem mais raro hoje em dia do que no passado, mas ainda há casos onde reescrever algum código Java em C/C++ pode proporcionar ganhos de desempenho importantes;

Eu não conheço nenhuma estatística que informe quantos leitores da JM, ou desenvolvedores Java em geral, já tiveram alguma dessas necessidades. No entanto, todos os principais IDEs para Java possuem plug-ins que dão suporte ao desenvolvimento em C/C++. Os IDEs Java mais maduros há tempos se tornaram verdadeiros “faz-tudo” multilinguagem, mas a maioria das linguagens suportadas geram bytecode para a JVM: Groovy, JRuby, Scala, JavaFX Script etc. As linguagens C/C++ são uma grande exceção; uma exceção importante o bastante para merecer hospedagem especial em IDEs normalmente dedicados à plataforma Java.

Neste artigo, vamos examinar o desenvolvimento em C/C++ do ponto de vista do desenvolvedor que trabalha primariamente com a plataforma Java. Mostraremos como usar os plug-ins C/C++ mais recentes do Eclipse 3.6 e do NetBeans 6.9.1, e discutiremos a integração entre Java e C/C++ através de JNI e JNA.

Instalação básica para C/C++

Há diversos compiladores para C/C++, alguns portáveis, outros específicos para determinadas plataformas. Além do compilador você precisará de um conjunto mais amplo de ferramentas para depuração, construção, linking etc. – o chamado toolchain. A opção mais “democrática” possível é, sem dúvida, o toolchain GNU, encabeçado pelos compiladores GCC (GNU Compiler Collection). Este toolchain é livre e gratuito, e suporta praticamente qualquer plataforma imaginável.

O leitor que usa Linux poderá instalar o GCC e outras facilmente pelo seu gerenciador de pacotes. Quem usa o Windows pode baixar o Cygwin, em cygwin.com. Independente da necessidade de C/C++, costumo ter o Cygwin sempre instalado em qualquer máquina Windows, pois este inclui muitas ferramentas de linha de comando extremamente úteis.

Observe que a instalação default do Cygwin não inclui todo o toolchain necessário para programar C/C++. Você terá que selecionar manualmente, na categoria Devel, pelo menos os seguintes itens: cmake, gcc, gcc-core, gcc-g++, gdb, make. Ao terminar a instalação, valide-a executando gcc --version na linha de comando (note que são dois '-'), o que deve exibir uma mensagem como:


  gcc-4 (GCC) 4.3.4 20090804 (release) 1
  Copyright (C) 2008 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

Se você fez esse teste com o Cygwin (a partir da shell CMD.EXE do Windows) e obteve uma mensagem de acesso negado, tente gcc-4, ou entre na shell bash antes de chamar o gcc. Para o leitor que quer ter várias versões do GCC instaladas, seja no Cygwin ou outro sistema operacional, recomendo configurar o GCC 4.x como default, ou configurar o IDE de forma a usar o GCC 4.

Para o usuário do Windows: Ainda não há a opção de utilizar o toolchain da Microsoft (compiladores e ferramentas do Windows SDK e Visual C++), pois este não é suportado nem pelo Eclipse CDT, nem pelo NetBeans C/C++. Há apenas suporte limitado (como execução de Makefiles externos), mas nesse caso não vejo conveniência em usar o IDE Java. Por outro lado, o GCC do CygWin não é compatível com a produção de DLLs para uso da JVM para Windows, de forma que o leitor que usa o Windows até poderá acompanhar as seções de JNI e JNA com o CDT ou NetBeans C/C++, mas terá que fazer a compilação final da DLL com algum compilador “nativo” do Windows (o Visual C++ Express é gratuito).

Começando com o NetBeans C/C++

Esta seção é dirigida ao leitor que prefere o NetNeans. Quem trabalha somente com o Eclipse pode pular esta seção.

Para instalar o suporte do NetBeans para C/C++, você pode usar um dos pacotes de instalação que incluem este plugin; para seguir este artigo recomendo baixar o pacote All, pois vamos precisar tanto de C/C++ quanto do suporte a Java. Quem já tinha o NetBeans instalado, pode pegar qualquer um dos dois pacotes que incluem C/C++ e instalar apenas este módulo de forma incremental.

Configuração

Uma vez instalado, o NetBeans C/C++ detectará seu toolchain GNU automaticamente. Para conferir, entre em Ferramentas>Opções. Todos os itens preenchidos na Figura 1 são exigidos; os que faltam (compilador Fortran e QMake) são opcionais. Se estiver faltando algum pacote, instale-o e depois comande Restaurar padrões para que o NetBeans detecte os programas que faltavam.

As outras abas da tela de C/C++ permitem configurar diversas outras opções como diretórios de include e detalhes de destaque sintático. Veja também a aba Editor para as opções de formatação, auto-completamento e templates, que ganham suporte específico para as linguagens C e C++.

Alô, Mundo

Vamos criar o clássico (ou segundo as más línguas, batido) “Alô Mundo”. Execute Novo Projeto>C/C++>Aplicativo de C/C++. Em Nome e local do projeto, defina o nome do projeto e escolha C como opção de linguagem para o arquivo principal main.

Edite o arquivo main.c gerado, acrescentando algumas linha para ficar como a Listagem 1.

Listagem 1. Alô Mundo em C.


  #include <stdio.h>
  #include <stdlib.h>
   
  int main (int argc, char** argv) {
    if (argc != 2)
      return EXIT_FAILURE;
   
    printf("Alo, %s!\n", argv[1]);
    return EXIT_SUCCESS;
  }

Configurando o toolchain GCC para o NetBeans

Figura 1. Configurando o toolchain GCC para o NetBeans.

Execute o projeto. Como este ainda não havia sido compilado, isso será feito automaticamente, gerando um log como o da Listagem 2; finalmente, veremos a mensagem gerada pelo programa.

Listagem 2. Log de build do programa C (com o NetBeans e Cygwin).


  "/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
  make[1]: Entering directory `/cygdrive/c/Workspaces/nb/TesteC'
  "/usr/bin/make"  -f nbproject/Makefile-Debug.mk dist/Debug/Cygwin_4.x-Windows/testec.exe
  make[2]: Entering directory `/cygdrive/c/Workspaces/nb/TesteC'
  mkdir -p build/Debug/Cygwin_4.x-Windows
  rm -f build/Debug/Cygwin_4.x-Windows/main.o.d
  gcc.exe    -c -g -MMD -MP -MF build/Debug/Cygwin_4.x-Windows/main.o.d -o build/Debug/Cygwin_4.x-Windows/main.o main.c
  mkdir -p dist/Debug/Cygwin_4.x-Windows
  gcc.exe     -o dist/Debug/Cygwin_4.x-Windows/testec build/Debug/Cygwin_4.x-Windows/main.o  
  make[2]: Leaving directory `/cygdrive/c/Workspaces/nb/TesteC'
  make[1]: Leaving directory `/cygdrive/c/Workspaces/nb/TesteC'
   
  CONSTRUIR BEM-SUCEDIDO (tempo total:  2s)  ... 

Quer ler esse conteúdo completo? Tenha acesso completo