Dúvida em JNA: CallBack [RESOLVIDO]

5 respostas
oddy.silva

Bom dia ao pessoal do GUJ.

Eu escrevi um arquivo em C que tem uma função cujo o retorno é uma estrutura.

struct estrutura *nome_funcao(){

/*Corpo do código, atribuição de valor a estrurura.*/

return estrutura;
}

Eu preciso passar essa estrutura pro Java. Daí, lendo a API do JNA, vi que para receber
estruturas do C no Java, devo criar uma classe que estenda Structure e que tenha uma interface
interna que estenda CallBack. Fiz assim:

/*Esta classe deverá ser responsável por receber uma estrura em C*/
public class ClasseEstrutura extends Structure{

   /*Interface interna*/
   public interface EstruturaASerRecebida extends CallBack(){
       /*método com o mesmo nome da função em C*/
       public Structure nome_funcao();
}

  /*Instância para poder acessar a interface interna*/
  public EstruturaASerRecebida estrutura;

}

Ok, agora que vem a dúvida. Pra quem conhece JNA, sabe que deve haver uma interface
que estende Library, e que todos os métodos dessa interface devem possuir os mesmos
nomes das funções em C. Se é assim, então eu não deveria ter escrito a classe acima,
e sim apenas ter feito:

public interface MetodosNativos extends Library{

public Structure nome_funcao();

}

Mas já tentei fazer isso e não funcionou.

Lendo na API do JNA, vi que pra usar o CallBack, deveria ter feito mais ou menos assim:

ClasseEstrutura ce = new ClasseEstrutura();
 /**Não entendi e nem encontrei esse método init*/ 
 lib.init(ce);
 Structure x = ce.estrutura.nome_funcao();

O que eu não entendi do código acima:

  • Quem é lib?
  • De onde vem esse método init?
  • Em qual classe esse código deve ser escrito?

Eles estão lá na página do JNA, mas eu realmente não entendi, pois acho que eles não deixaram muito
claro… Eu só estou pedindo um help pro pessoal porque hoje não consegui acessar nem o site do JNA e nem a API.
Tá dando pau e eu não sei se é aqui ou lá. De qualquer maneira, se alguém puder me ajudar a entender esses
carinhas do último exemplo, fico grato. Abraço.

5 Respostas

oddy.silva

A página do JNA está no ar de novo!

Só pro pessoal ver qual a parte do exemplo que não entendi, aqui vai o link:

https://jna.dev.java.net/javadoc/overview-summary.html#callbacks

J

Pelo que eu entendi, vc não precisa de um ponteiro pra um função pra retornar sua struct. Somente precisa implementar a interface.

public interface CLibrary extends Library {

int atol(String s);

}

pode muito bem ser assim:

public interface CLibrary extends Library {

struct *sua getStruct();

}
oddy.silva

Hum, entendi.
Eu cheguei a ler isso e até mudei meu código. De acordo com a especificação da API do JNA, quando uma função retorna um ponteiro para estrutura,
deve-se criar o equivalente dessa estrutura no JAVA. https://jna.dev.java.net/javadoc/overview-summary.html#structures

Daí eu criei uma, mas não está funcionando. Abaixo os códigos:

/**No C*/

/*Veja que tem um enum, e eu também tive de mapeá-lo no Java*/
enum fp_data_type {
	PRINT_DATA_RAW = 0, /* memset-imposed default */
	PRINT_DATA_NBIS_MINUTIAE,
};

/*A estrutura*/
struct fp_data {
	uint16_t driver_id;
	uint32_t devtype;
	enum fp_data_type type;
	size_t length;
	unsigned char data[0];
};

O que eu fiz no Java:

/*Mapeando a estrutura no JAVA*/
public class StructureFPData extends Structure{

    public int driver_id;
    public long devtype;
    public enum fp_data_type {

        PRINT_DATA_RAW,
        PRINT_DATA_NBIS_MINUTIAE;
    }
    public int lenght;
    public String data;

}

Daí eu tenho a minha interface que aponta para a função que retorna uma estrutura:

public interface ReturnsAStructure extends Library{

    public StructureFPData nome_funcao();

}

E faço a chamada para obter a estrutura numa outra classe:

public StructureFPData novaEstrutura;

ReturnsAStructure returnValue = Native.loadlibrary(blá blá blá...);

novaEstrutura = returnValue.nome_funcao();

Só que a aplicação quebra no meio do caminho. Creio que o problema esteja nos tipos do C e nos tipos que eu usei para mapear a estrutura no Java. Alguma idéia?

oddy.silva

Na verdade, está quebrando na hora de retornar a estrutura. A função no C é executada, tudo legal, mas na hora do retorno é que dá pau.

oddy.silva

Bom, depois de passar o dia todo lendo a API do JNA, finalmente resolvi meu problema: era só corrigir a maneira como mapeei a estrutura.

Da maneira que passei, haviam dois erros:

public class StructureFPData extends Structure{  
   
     public int driver_id;  
     public long devtype;  
           /**Um erro aqui**/    
           public enum fp_data_type {  
   
         PRINT_DATA_RAW,  
         PRINT_DATA_NBIS_MINUTIAE;  
     }  
     public int lenght;  
     /**Outro erro aqui*/
     public String data;  
   
}

Primeiro erro:
Enuns podem ser mapeados no Java diretamente para o tipo inteiros.

Segundo erro:
Eu criei uma String, mas na verdade deveria mapear um Byte! Qualquer coisa no C que seja “unsigned char var[0]” é mapeado para o tipo byte do Java.
Resumindo, o correto é:

public class StructureFPData extends Structure{  
    public int driver_id;
    public long devtype;
    public int type;
    public int lenght;
    public byte data;
}

O Resto tá certinho. Um abraço a todos. Viva as API’s!

Criado 3 de julho de 2009
Ultima resposta 3 de jul. de 2009
Respostas 5
Participantes 2