Revista Do Linux
 
  
  
 

  Capa
  Evento
  Serviço Público
  Corporativo
  Tutorial ECF Remota
  Tutorial Xdm
  Software
  Entrevista
  Estudo de Caso
  Distro
assinantes
 

Java e Flagship

"Um futuro próspero é feito de se cultivarem comunidades como a do Linux. Eis mais uma semente...".

Devo dizer de antemão que aprecio imensamente a linguagem Flagship. Apesar de o Flagship contar com conceitos avançados, como objetos, inline C, etc, ela ainda carece dos aperfeiçoamentos que outras linguagens já incorporam e disponibilizam facilmente há muito tempo. Não cabe aqui apresentar cada um destes aperfeiçoamentos que lhe faltam; é uma linguagem que nos possibilitou usar códigos do antigo Clipper e, portanto, forneceu uma sobrevida a vários de nossos sistemas. Recentemente, o Visual Flagship foi lançado com a intenção de permitir a criação de programas com interfaces visuais. Quem utilizou a nova versão percebeu que, de fato, interfaces visuais podem ser criadas, mas muito longe da beleza e sofisticação visuais das linguagens hoje disponíveis. Então, como criar uma interface visual de alto nível como aquelas que vemos em programas feitos com o Delphi, VisualBasic, etc., e integrá-la ao código já escrito em FS? Melhor ainda, isto é possível?

Quatro letras são a resposta: J-A-V-A. Java é uma das melhores linguagens que já encontrei, e pretendo demonstrar isto permitindo sua integração com programas escritos em Flagship. Hoje, grandes empresas como IBM, HP, Sun, etc., utilizam-na largamente. Para detalhes sobre Java, compre uma das várias publicações disponíveis, ou acesse a Internet. No final deste artigo, apresento alguns 'links' úteis.

Antes de continuar, por favor, dê uma olhada na Figura 1. Que tal? A interface foi construída com o NetBeans rodando sob o SkinLF mas, em alguns casos, uso o JBuilder ou ainda o simples e poderoso 'vi'. São ferramentas 'freeware' ou têm uma versão 'freeware'. Em todo caso, foram usadas somente para o posicionamento dos componentes no 'frame'. Esta parte é simples e tão prazerosa que chega a viciar. Vamos dividir nossa missão de integração em três partes. Primeiro, utilizaremos um recurso avançado do Flagship: Objetos. A filosofia de objetos no FS foi muito bem implementada, e é um recurso que eu utilizo, pois nada melhor do que criar objetos para se comunicar com outra linguagem que seja fortemente orientada a objetos. Segundo, o inline C; outra poderosa característica do FS que permite a integração com a linguagem C. C? Não iríamos usar Java? Sim. Mas, pensemos um pouco no assunto: o Flagship não entende Java diretamente, Java por sua vez não entende Flagship, entretanto ambas permitem a implementação de código escrito em C. Conclusão: C será então nossa linguagem intermediária! Finalmente, na terceira parte, vamos fundir tudo para construir uma interface realmente funcional. A esta altura, talvez você esteja se perguntando se não é melhor esperar melhoramentos no Visual FlagShip. Conclua a leitura do artigo e veja por si mesmo.

Primeira Parte: Objetos

A programação com objetos é mais clara e eficiente do que a programação procedural. Esta seção será mais bem compreendida se o leitor já tiver algum conhecimento prévio sobre a teoria da programação orientada a objetos.

Vamos usar conceitos simples do mundo da programação baseada em objetos, tais como: atributos e operações (métodos). Não pretendo desenvolver passo a passo tudo o que vamos precisar, pois este artigo provavelmente se estenderia além do limite aceitável para publicação. O Quadro 2 declara um objeto em Flagship.

Esta é a estrutura básica de um objeto em FS. Para mais detalhes, consulte a seção OBJ do manual que acompanha o produto. Há vários exemplos práticos na seção CMD:CLASS, INSTANCE - eu leria tudo, caso quisesse usar seriamente objetos.

Segunda parte: inline C

O inline C consiste em permitir que código escrito em C seja inserido diretamente em programas FlagShip. Uma descrição detalhada pode ser vista no manual do produto na seção EXT sob o nome de Open C System API - certamente mais uma agradável leitura para o fim de semana. A Multisoft fez um ótimo trabalho, na minha opinião, e, graças a este recurso, nossa missão foi grandemente facilitada. O Quadro 3 contém uma amostra do inline C.

Olhando atentamente percebemos que é o nosso velho e conhecido C. Nos exemplos fornecidos no manual, vemos que a partir de um bloco em C é possível enxergar as variáveis declaradas na parte em FS.

Terceira parte: A Fusão

A linguagem Java possibilita o acesso aos recursos nativos em um dado ambiente operacional. Isto é feito através da JNI Java Native Interface. A JNI no Linux vem praticamente na forma de bibliotecas dinâmicas - comumente com a extensão '.so' ~V que, quando 'linkadas' com uma dada aplicação ou biblioteca, permite às classes em Java invocar funções declaradas explicitamente para este fim. Digo 'explicitamente declaradas' por que na declaração das funções são necessárias algumas adaptações. O Quadro 4 mostra tais adaptações.

Um outro recurso importante que a JNI oferece é a chamada da máquina virtual Java (JVM) a partir de outra aplicação escrita, por exemplo, em FlagShip. Esta é precisamente a nossa intenção, ou seja, iniciar uma JVM de dentro de um programa FlagShip e colocá-la a nosso serviço. Portanto, mãos à obra...

Embora, a primeira vista, o código que estamos a ponto de produzir pareça complexo, ele realmente não é, pois tudo é feito sempre da mesma forma. Olhando o código em FS no Quadro 5, percebemos que a primeira coisa que o programa faz é criar a máquina virtual Java. Isto se torna óbvio, já que as próximas funções necessitam interagir com uma JVM já inicializada. Em seguida, abrimos um DBF, criamos um único índice e chamamos a função 'RegFunc'. Não procure pela declaração desta função no código em FS, pois ela é declarada em nosso mediador escrito em C. Esta função tem o objetivo de registrar as funções FS que serão acessíveis a partir do código em Java. Criamos um objeto chamado 'ofrm' (implementado em 'jvrqjvm.prg') e, em seguida, invocamos através dele o método estático setUI da classe 'Pesquisa', que ativa o SkinLF; por fim, exibimos nossa janela gráfica. A partir de agora, nossa pequena aplicação Java entra em cena. Apesar de executar uma simples operação de consulta, o código em Java pode ser expandido para executar tarefas mais elaboradas. Falo do acesso, por exemplo, de funções complexas de manipulação de dados, operações com DBFs, substituição de interfaces com usuários, etc.

Para executar esta simples tarefa de consulta, fizemos uso de alguns dos recursos mais avançados em ambas as linguagens. E, por falar em avanço, por que não usar a UML (Unified Modeling Language) para criar um diagrama geral das dependências em nossa pequena aplicação? Acredito que é melhor do que tentar deduzi-las a partir do código puro. Na Figura 6, percebemos claramente que o item mediador.c faz a ponte entre as duas linguagens. Os itens restantes não são realmente novos. Na realidade, fazem parte da prática normal de programação em cada uma das linguagens utilizadas.

No diagrama, abaixo de cada um dos itens, notamos as operações permitidas. As palavras em itálico indicam que embora a operação exista, ela não é realmente implementada naquele ponto. Por exemplo, o código real de showFrame está na classe 'Pesquisa' e não no objeto FlagShip 'jvrqjvm'. Ainda que isto seja verdade, permitimos que a operação apareça no interesse de garantirmos a construção de uma abstração fidedigna. Outro motivo, obviamente, é o de demonstrar que o método está disponível para chamada naquele objeto em particular.

Juntamente com os arquivos contendo o código fonte nesta matéria, existe um arquivo Makefile que, de certa forma, dita a ordem e estabelece uma precedência durante o processo de compilação. Esta ordem é importante dentro do escopo de cada ambiente. Em outras palavras, você receberá mensagens de erros se tentar compilar javaflag.prg antes de jvrqjvm.prg, pois o primeiro depende formalmente do segundo. Contudo, javaflag.prg não depende da classe 'Pesquisa' diretamente. Portanto, as compilações podem ocorrer em tempos diferentes. O fato acima demonstra algo muito importante: caso queira atualizar a parte de sua aplicação escrita em Java, basta compilá-la corretamente e efetuar a atualização independentemente do código em FS. Isto funciona para os dois lados. Existe, contudo, uma dependência em tempo de execução que dará origem a erros se, por exemplo, você invocar um método não existente.

Bem, aqui está o caminho das pedras para quem desejar fundir código FlagShip com objetos em Java. O potencial é grande, não respondemos a todas as questões, mas esperamos ter lançado alguma luz para aqueles que desejam começar. "O princípio não é tão obscuro assim afinal".

Quadro 2

CLASS jvClass
  INSTANCE jv_clsname := "" AS CHARACTER

ACCESS jv_clsname CLASS jvClass AS CHARACTER
  Return jv_clsname

ASSIGN jv_clsname( vl ) CLASS jvClass
  jv_clsname := vl
  Return jv_clsname

METHOD Init( fg_nmcls ) CLASS jvClass
  // Todo código contido nesta seção será
  // executado na criação do objeto
  Return

METHOD isValidDate( dt ) CLASS jvClass
  Local bRet := .T.
  IF Empty(CtoD(dt))
    bRet := .F.
  Endif
  Return bRet

METHOD ...

e assim por diante
        .

Quadro 3

#Cinline
{
  for( iCt = 1; iCt <= 10; iCt++ )
  {
    fprintf( stderr, ": %i : \r\n", iCt );
  }
}
#endCinline

Quadro 4

#include 
#include 
#include "HelloWorld.h"

JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, object obj)
{
    printf("Hello World!\n");
    return;
}

Quadro 5

#include "jvclasses.fh"

Function Main()
  IF jvmUpJVM()
    Use "clientes.dbf" Alias cli Shared New
    Index On cli->CODIGO to cli1
    Set Index to cli1
    RegFunc()
    Local ofrm := jvrqJVM{} AS jvrqJVM
    ofrm:setUI()
    ofrm:showFrame()
  Else
    Alert( "Erro ao carregar JVM" )
  Endif
  Return

Function findCli( codigo )
  Sele cli
  Go Top
  IF DbSeek(Padr(codigo, Len(&(IndexKey(0)))),.F.)
  Return { .T., cli->DESCRICAO }
  Endif
  Return { .F., "Erro na procura de registro" }

Para Saber Mais:
JavaSDK - java.sun.com
Flagship - www.fship.com
NetBeans - www.netbeans.org
SkinLF - www.l2fprod.com
Vim - www.vim.org
JBuilder - www.borland.com/jbuilder
UML - www.omg.org/uml
Veja código-fonte referente a este artigo no diretório /doc de nosso CD


Ricardo Delamar Roque - roque@gdysafety.com.br

A Revista do Linux é editada pela Conectiva S/A
Todos os Direitos Reservados.

Política de Privacidade
Anuncie na Revista do Linux