2016-03-22 32 views
5

Sto iniziando a utilizzare JNA per comunicare con un dispositivo sull'interfaccia RS485 di un computer. Sorprendentemente per me sono arrivato a buoni risultati molto rapidamente. Ma ora sono bloccato da un semplice problema. La libreria che uso accetta un puntatore a un puntatore di struct. La firma reale èJNA: imposta il puntatore struct su NULL

func(Struct1 **, Struct2 **, Struct3 *, Struct4 *, long)

Ora per indicare la dimensione del primo parametro della biblioteca si aspetta che l'ultimo puntatore a un puntatore NULL. Questo è ciò che fallisce. A seguito di codice è quello che ho provato finora:

Struct1.ByReference[] s = (Struct1.ByReference[]) new Struct1.ByReference().toArray(size); 
    int pos = 0; 

    // ... 
    // for loop to set the s[pos] struture values 
    for(pos = 0; pos < size - 1; pos++) 
    // ... 

    // Now set the last array element to a null pointer to indicate end-of-list 
    s[pos].getPointer().setPointer(0, null);// Following does not work: results in zero memoried structure 
    s[pos] = null; // Following does not work wither: NullPointerException at com.sun.jna.Structure.autoWrite 

EDIT 1

s[pos] = new Struct1.ByReference(Pointer.NULL); // results in zero memoried structure as well 

EDIT 2

Secondo la domanda di TechnoMage. Se dovessi scrivere codice C sarebbe probabilmente sembrare qualcosa di simile:

Struct1 **s = malloc(n * sizeof(Struct1*)); 

for(int i=0; i<n; i++) 
{ 
    if(i == n -1) 
    { 
     s[i] = NULL; 
    } 
    else 
    { 
     s[i] = malloc(sizeof(Struct1)); 
     s[i].bla = value; 
     .... 
    } 
} 

Ma si ricordi: io non sono molto abile in C/C++. Considero Java come il mio dominio.

Qualcuno ha avuto un problema simile? Forse non vedo il legno per gli alberi ...

Grazie in anticipo.

+0

Si prega di includere un esempio di utilizzo nativo. Le dichiarazioni delle funzioni per le variazioni del puntatore possono essere ambigue senza quel contesto: non c'è modo di distinguere tra un puntatore a un array, un puntatore a un singolo valore del puntatore o molte altre varianti. – technomage

+0

Cosa intendi con "esempio di utilizzo"? La libreria è stata adottata dal codice di un dispositivo incorporato che esegue FreeRTOS, un sistema operativo in tempo reale open source. Non ho alcun codice nativo oltre al file di intestazione che esporta i metodi della libreria. –

+0

Se si dovesse scrivere codice in 'C' che accede alla libreria nel modo desiderato, come si presenterebbe? – technomage

risposta

0

Le strutture in JNA sono puntatori, quindi quello che realmente serve qui è un puntatore a un (puntatore a un) Struttura, che è un PointerByReference - nel tuo caso, un array di essi.

Dato il codice esempio precedente, si creerà l'array di strutture, un minore di n:

Struct1[] struct1Array = new Struct1[n-1]; 

Questo assegna solo la memoria di Java per l'array.

Si procederà ora un'istanza e scrivere le modifiche apportate alla memoria nativa:

for (int i = 0; i < n-1; i++) { 
    struct1Array[i] = new Struct1(); 
    struct1Array[i].bla = value; 
    struct1Array[i].write(); 
} 

Il new Struct1() alloca la memoria lato nativo per queste strutture. È anche possibile utilizzare il metodo Structure.toArray() per fare ciò; Lo faccio intenzionalmente un po 'più manuale e di basso livello per cercare di chiarire cosa sta succedendo.

Quindi verrà creato un array PointerByReference corrispondente per contenere i puntatori a queste strutture. Aggiungere un elemento aggiuntivo per il null:

PointerByReference[] pbrArray = new PointerByReference[n]; 

Ancora una volta, questa è solo l'allocazione java-side. E poi si riempie con puntatori ai puntatori alla struttura, ottenuti dal metodo Structure.getPointer():

for (int i = 0; i < n-1; i++) { 
    pbrArray[i] = new PointerByReference(struct1Array[i].getPointer()); 
} 
pbrArray[n - 1] = new PointerByReference(Pointer.NULL); 

Il new PointerByReference() qui alloca la memoria lato nativo per il puntatore stesso, che punta alla struttura nativa lato allocata in precedenza.

Da come ho capito la tua domanda iniziale, passerai questa matrice PointerByReference alla tua funzione, che presumibilmente aggiorna le tue strutture.

Poiché si sono creati i due array in questo modo, è possibile tenere traccia della corrispondenza da un indice di array. Potrebbe essere necessario scorrere l'array della struttura e read() la memoria nativa nella struttura lato Java per eseguire ulteriormente l'elaborazione con esso. In genere quando si lavora direttamente con Structures passando ai metodi che eseguono automaticamente e automaticamente, ma quando si utilizza un PointerByReference per fare riferimento indirettamente alla Struttura, JNA non è così amichevole.

In alternativa al tracciamento dei due array con gli indici corrispondenti, è possibile "dimenticare" l'assegnazione iniziale della struttura e ripristinarla successivamente utilizzando il metodo PointerByReference.getValue() sull'array per recuperare un puntatore alla memoria per la struttura e quindi creare un'istanza una nuova struttura che utilizza quel puntatore nel suo costruttore (ad esempio new Struct1(pbr.getValue()) che chiama super() con quel puntatore).