Search code examples
javajna

How to access output parameter value


It's the first time I need to use JNA, I've read something about it and there are still some stuff not very clear for me...

Well, I need to use a .dll from a third party. They provided me their library .h file.

/*
 * Biblioteca de Automação Comercial
 *
 * API para facilitar integração com CTF Client
 */

/*prevent multiple includes*/
#ifndef _H_AUTTAR_BIBLIOTECA_AC_CTF
#define _H_AUTTAR_BIBLIOTECA_AC_CTF

/*useful definitions*/
#ifndef BOOL
  #define BOOL int
#endif

#ifndef TRUE
  #define TRUE 1
#endif

#ifndef FALSE
  #define FALSE 0
#endif

#ifndef NULL
  #ifdef __cplusplus
#define NULL 0
  #else
    #define NULL ((void *)0)
  #endif
#endif

/*OS specific*/
#ifdef _WIN32
  #define CTF_API  __stdcall
#else
  #define CTF_API  
#endif

/*make this code usable by C++*/
#ifdef __cplusplus 
  extern "C" {
#endif

/*API function calls*/
void CTF_API iniciaClientCTF(char* resultado,   /* out */
                             char* terminal,    /* in */
                             char* versao_ac,   /* in */
                             char* nome_ac,     /* in */
                             char* num_sites,   /* in */
                             char* lista_ips,   /* in */
                             char* criptografia,/* in */
                             char* log,         /* in */
                             char* interativo,  /* in */
                             char* parametros   /* in */
                             );

void CTF_API iniciaTransacaoCTF(char* resultado, /* out */
                                char* operacao,  /* in */
                                char* valor,     /* in */ 
                                char* num_doc,   /* in */ 
                                char* data_cli,  /* in */ 
                                char* num_trans  /* in */ 
                                );

void CTF_API iniciaTransacaoCTFext(char* resultado,  /* out */
                                   char* operacao,   /* in */
                                   char* valor,      /* in */
                                   char* num_doc,    /* in */
                                   char* data_cli,   /* in */
                                   char* num_trans,  /* in */
                                   char* dados);     /* in */

void CTF_API continuaTransacaoCTF(char* resultado, /* out */
                                  char* comando,   /* in/out */
                                  char* num_sc,    /* in/out */
                                  char* p_sc,      /* in/out */
                                  char* tam_sc,    /* in/out */
                                  char* aux);      /* in/out */

void CTF_API finalizaTransacaoCTF(char* resultado, /* out */
                                  char* confirmar, /* in */
                                  char* num_trans, /* in */
                                  char* data_cli );/* in */

/*make this code usable by C++*/
#ifdef __cplusplus 
    }
#endif

/*end of multiple-include prevention*/
#endif

My mapping interface is

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface ICTFClient extends Library {

    ICTFClient INSTANCE = (ICTFClient) Native.loadLibrary("ctfclient", 
ICTFClient.class);

    public void iniciaClientCTF(byte[] resultado, 
                            byte[] terminal, 
                            byte[] versao_ac, 
                            byte[] nome_ac,
                            byte[] num_sites, 
                            byte[] lista_ips, 
                            byte[] criptografia, 
                            byte[] log, 
                            byte[] interativo,
                            byte[] parametros);

    public void iniciaTransacaoCTF(byte[]  resultado, 
                                byte[]  operacao, 
                                byte[]  valor, 
                                byte[]  num_doc,
                                byte[]  data_cli, 
                                byte[]  num_trans);

    public void iniciaTransacaoCTFext(byte[]  resultado, 
                                byte[]  operacao, 
                                byte[]  valor, 
                                byte[]  num_doc,
                                byte[]  data_cli, 
                                byte[]  num_trans,
                                byte[] dados);

    public void continuaTransacaoCTF(byte[]  resultado, 
                                byte[]  comando, 
                                byte[]  num_sc, 
                                byte[]  p_sc,
                                byte[]  tam_sc, 
                                byte[]  aux);


    public void finalizaTransacaoCTF(byte[]  resultado, 
                                byte[]  confirmar, 
                                byte[]  numTrans, 
                                byte[]  dataTransacao);
}

My question is: How can I access the output parameter returned by the library? Do you think my interface mapping is correct?


Solution

  • An "out" argument usually means that the function will write to the pointer provided to it. The function doesn't seem to take the output buffer's size as an argument, so you'll need to read the library's documentation to find out how big of a buffer the output needs (how many bytes).

    byte[] outputBuf = new byte[4096]; // Change 4096 to the correct size
    ICTFClient.INSTANCE.iniciaClientCTF(outputBuf, /* ... */);
    
    // If the output is not ASCII, e.g. encoded in an encoding which supports Portugese characters, 
    // pass the correct CharSet instead
    String output = new String(outputBuf, StandarsCharsets.US_ASCII);
    System.out.println("Output: " + output);
    

    By the way, if all of the char* in-params are strings, just use a Java String - JNA will work with it.