2015-11-06 3 views
7

Ho la seguente struttura C che deve essere mappata su Java. Perché ho bisogno di chiamare un metodo da una DLL generata dal codice C. Quanto segue è la mia struttura.Come posso mappare i seguenti elementi di una struttura C su Java?

typedef struct _ipj_iri_device 
{ 
IPJ_READER_CONTEXT reader_context; 
IPJ_READER_IDENTIFIER reader_identifier; 
uint32_t    receive_timeout_ms; 

/* Internal Only */ 
uint8_t    sync_state; 
bool     wait_for_response; 
uint32_t    frame_length; 
uint32_t    receive_index; 
uint8_t    receive_buffer[IPJ_RECEIVE_BUFFER_SIZE]; 

#if !defined(IRI_RX_ONLY) 
uint8_t    transmit_buffer[IPJ_TRANSMIT_BUFFER_SIZE]; 
#endif 

} ipj_iri_device; 

L'IPJ_READER_CONTEXT e IPJ_READER_IDENTIFIER si presenta come di seguito.

typedef void* IPJ_READER_CONTEXT; 
typedef void* IPJ_READER_IDENTIFIER; 

Come analizzare questi due elementi per eseguire il mapping su Java? Per favore consiglio

+0

Non è possibile lavorare esplicitamente con i puntatori (void) in java. Il più vicino a un vuoto * utilizza un oggetto come tipo (e salva le informazioni pertinenti in un oggetto creato individualmente per IPJ_READER_CONTEXT e IPJ_READER_IDENTIFIER) – ParkerHalo

+0

Se stai provando a chiamare una funzione di libreria condivisa da Java, dove la libreria era scritto in C potresti trovare SWIG è tuo amico? – bph

+0

Non ho potuto usare swig perché non posso modificare il codice C esistente per adattarlo ai requisiti. – mayooran

risposta

-1

Aah dopo una lunga ricerca qui interessato su OOP vs paradigma funzionale. Quindi qui possiamo risolverlo come. Ecco i passaggi base.

  • Nome della struttura come classe.
  • Mettere tutti gli attributi della struttura come attributi di classe.

  • Per quei void *, in java è possibile utilizzare le variabili di riferimento.

  • quindi per un'istanza di struct come hai ottenuto la struttura con il nome di ipj_iri_device, basta creare un oggetto della classe denominato in bullet one.

    public class _ipj_iri_device{ 
        int IPJ_RECEIVE_BUFFER_SIZE ; 
        //get a value from whereever the input is coming ,assign it to buffersize 
        IPJ_READER_CONTEXT reader_context; 
        IPJ_READER_IDENTIFIER reader_identifier; 
        boolean wait_for_response; 
        uint32_t receive_timeout_ms; 
        //here uint32_t is a type i asumed .You will have to define it explicitly 
    
        //rest of the vaariables/members of structure 
    } 
    
+0

Se creo una variabile di riferimento, quali dovrebbero essere le sue proprietà? Cosa devo fare all'interno della classe del tipo di riferimento? Per favore consiglio – mayooran

+0

IPJ_READER_CONTEXT e IPJ_READER_IDENTIFIER sono i tipi (fondamentalmente una classe), dovrai definirli in base alle tue necessità ma il loro tipo di reso sarebbe nullo nel tuo caso. – shaun

+0

puntatore vuoto si riferisce solo a un indirizzo di memoria giusto? Quindi, se definisco una classe del genere, non farò mettere qualcosa all'interno della classe. Questo è quello che non capisco. Cosa contengono queste classi? – mayooran

0

Ecco un esempio di ciò che la vostra struttura potrebbe essere simile utilizzando JNA:

public class ipj_iri_device extends Structure { 
    Pointer    reader_context; 
    Pointer    reader_identifier; 
    int     receive_timeout_ms; 
    /* Internal Only */ 
    byte     sync_state; 
    // field size depends on size of 'bool'; "byte" is usually correct 
    byte     wait_for_response; 
    int     frame_length; 
    int     receive_index; 
    byte[]    receive_buffer = new byte[IPJ_RECEIVE_BUFFER_SIZE]; 
    // may or may not be used, check your native compile flag 
    byte[]    transmit_buffer = new byte[IPJ_TRANSMIT_BUFFER_SIZE]; 
} 

È possibile definire le strutture che sostengono i campi reader_context e reader_identifier se avete bisogno di loro contenuto. In caso contrario, è sufficiente passarli in giro come generico Pointer.

EDIT

Queste strutture possono essere utilizzati indipendentemente dal resto della JNA, tutto ciò che serve è una rappresentazione Pointer della memoria nativa per spostare i dati avanti e indietro.

+0

Devo avere getter e setter per gestire gli elementi della struttura? Funziona come la struttura C#? Per favore consiglio – mayooran

+0

E non ho bisogno di implementare la classe di struttura con Structure.ByReference – mayooran

+0

JNA utilizza per semantica la semantica di riferimento per i parametri di funzione, quindi non è richiesto un esplicito 'Structure.ByReference'. 'Structure.read()' e 'Structure.write()' si occupano dei valori dei campi di sincronizzazione con la memoria nativa e vengono chiamati automaticamente da JNA prima e dopo le chiamate alle funzioni native. – technomage

0

È possibile utilizzare JNIWrapper per mappare la struttura C su Java e chiamare la funzione dalla DLL.

Il wrapper per la struttura data sarà simile mostrato di seguito (i valori per le dimensioni costanti devono essere cambiato):

import com.jniwrapper.*; 

public class IpjIriDevice extends Structure 
{ 
    private static final int IPJ_RECEIVE_BUFFER_SIZE = 0; 
    private static final int IPJ_TRANSMIT_BUFFER_SIZE = 0; 

    private Pointer.Void reader_context = new Pointer.Void(); 
    private Pointer.Void reader_identifier = new Pointer.Void(); 
    private UInt32 receive_timeout_ms = new UInt32(); 
    private UInt8 sync_state = new UInt8(); 
    private Bool wait_for_response = new Bool(); 
    private UInt32 frame_length = new UInt32(); 
    private UInt32 receive_index = new UInt32(); 
    private PrimitiveArray receive_buffer = new PrimitiveArray(UInt8.class, IPJ_RECEIVE_BUFFER_SIZE); 
    private PrimitiveArray transmit_buffer = new PrimitiveArray(UInt8.class, IPJ_TRANSMIT_BUFFER_SIZE); 

    public IpjIriDevice() 
    { 
     init(new Parameter[] { 
      reader_context, 
      reader_identifier, 
      receive_timeout_ms, 
      sync_state, 
      wait_for_response, 
      frame_length, 
      receive_index, 
      receive_buffer, 
      transmit_buffer 
     }); 
    } 

    public long getReaderContext() 
    { 
     return reader_context.getValue(); 
    } 

    public long getReaderIdentifier() 
    { 
     return reader_identifier.getValue(); 
    } 

    public long getReceiveTimeoutMs() 
    { 
     return receive_timeout_ms.getValue(); 
    } 

    public void setReceiveTimeoutMs(long value) 
    { 
     receive_timeout_ms.setValue(value); 
    } 

    public long getSyncState() 
    { 
     return sync_state.getValue(); 
    } 

    public void setSyncState(long value) 
    { 
     sync_state.setValue(value); 
    } 

    public boolean getWaitForResponse() 
    { 
     return wait_for_response.getValue(); 
    } 

    public void setWaitForResponse(boolean value) 
    { 
     wait_for_response.setValue(value); 
    } 

    public long getFrameLength() 
    { 
     return frame_length.getValue(); 
    } 

    public void setFrameLength(long value) 
    { 
     frame_length.setValue(value); 
    } 

    public long getReceiveIndex() 
    { 
     return receive_index.getValue(); 
    } 

    public void setReceiveIndex(long value) 
    { 
     receive_index.setValue(value); 
    } 

    public PrimitiveArray getReceiveBuffer() 
    { 
     return receive_buffer; 
    } 

    public PrimitiveArray getTransmitBuffer() 
    { 
     return transmit_buffer; 
    } 

    public Object clone() 
    { 
     IpjIriDevice result = new IpjIriDevice(); 
     result.initFrom(this); 
     return result; 
    } 
} 

Se avete bisogno di un puntatore alla istanza di struttura, è necessario creare il puntatore istanza di classe:

IpjIriDevice structureInstance = new IpjIriDevice(); 
Pointer structurePtr = new Pointer(structureInstance); 

Dopodiché, è possibile utilizzare l'istanza del puntatore per passare il parametro della funzione. Il codice di seguito viene illustrato come caricare la libreria e chiama la funzione da esso:

DefaultLibraryLoader.getInstance().addPath(LIB_PATH); 
Library library = new Library(LIB_NAME); 
Function function = library.getFunction(FUNCTION_NAME); 
long errorCode = function.invoke(returnValue, structurePtr); 

Se la struttura viene modificata dopo la chiamata, tutte le modifiche saranno disponibili nell'oggetto structureInstance.

Come potete vedere, in questo caso non è necessario scrivere alcun codice nativo aggiuntivo.

È possibile trovare ulteriori dettagli sull'utilizzo di JNIWrapper nel suo programmer's guide. Inoltre, c'è lo JNIWrapper forum che contiene le risposte a molte domande popolari.

Problemi correlati