2010-11-27 30 views
7

Comment puis-je appeler une méthode avec cette signature de méthode en C à partir de JNA?Comment obtenir un nouveau pointeur en Java?

int open_device(context *ctx, device **dev, int index); 

Les deux dernières lignes de la méthode C ressemblent à ceci:

*dev = pdev; 
return 0; 

C'est la seule utilisation de dev dans cette méthode. Cela signifie que je dois passer un pointeur vers un pointeur vide vers la méthode, non? La méthode remplit alors le pointeur vide avec l'adresse d'un objet device et je peux passer le pointeur vers le périphérique à d'autres méthodes.

Ma question est: Est-ce la bonne façon de faire cela? Si c'est le cas, comment allouer un nouveau pointeur depuis Java?


Sur la base de la réponse acceptée, je l'ai fait:

Memory p = new Memory(Pointer.SIZE); 
Memory p2 = new Memory(Pointer.SIZE); 
p.setPointer(0, p2); 
nativeLib.open_device(ctx, p, index); 
return p2; 
+0

Juste curieux: votre code mis à jour a-t-il fonctionné pour vous? Il semble que vous définissiez '* p = p2' mais la fonction C ferait alors' * p = pdev', écrasant ainsi la valeur. – casablanca

+0

@casablanca: Oui, je l'ai testé, ça marche. – thejh

+0

@thejh savez-vous comment gérer l'exception invalidMemoryAccess créée en raison d'adresses mémoire invalides pointées? – mayooran

Répondre

9

Il semble que la JNA Pointer classe a setPointer et getPointer méthodes pour permettre plusieurs indirection, et la classe Memory réellement « affecter » les objets natifs. Donc, vous devriez être en mesure de faire quelque chose comme: (je devine juste de la documentation de la JNA, je ne l'ai pas testé cette)

Pointer pDev = new Memory(Pointer.SIZE); // allocate space to hold a pointer value 
// pass pDev to open_device 
Pointer dev = pDev.getPointer(0);  // retrieve pointer stored at pDev 
+0

Ah, que 'nouvelle mémoire (Pointer.SIZE);' semble que c'est ce dont j'ai besoin, merci. – thejh

0

Il n'y a pas de pointeurs en Java, seules les références.

Vous ne pouvez pas réaffecter une référence lorsque vous la transmettez à des méthodes, car vous les transmettez par valeur. Tout est passé en valeur en Java.

Vous pouvez réécrire cette méthode pour instancier une nouvelle instance du périphérique et renvoyer cette valeur au lieu d'un int.

+3

@duffymo: Je parlais de JNA Pointers: https://jna.dev.java.net/javadoc/com/sun/jna/Pointer.html – thejh

+0

Il est possible de le faire sans JNA. Il vous suffit de renvoyer la nouvelle référence à l'objet Device que vous instanciez au lieu d'un int. – duffymo

+2

@duffymo: Et comment puis-je accéder à une bibliothèque c (libbla.so) en utilisant Java sans ce contenu explicitement natif? – thejh

0

encore meilleure réponse. Vous voudrez peut-être allouer (malloc etc) en fonction de la longueur de la chaîne Java. L'exemple ci-dessous est un test unitaire du projet JNA.

public void testGetSetStringWithDefaultEncoding() throws Exception { 
    final String ENCODING = Native.DEFAULT_ENCODING; 
    String VALUE = getName(); 
    int size = VALUE.getBytes(ENCODING).length+1; 
    Memory m = new Memory(size); 
    m.setString(0, VALUE); 
    assertEquals("Wrong decoded value", VALUE, m.getString(0)); 
}