9

How can I call a method with this method signature in C from JNA?

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

The last two lines of the C method look like this:

*dev = pdev;
return 0;

That's the only use of dev in that method. That means that I have to pass a poiner to an empty pointer to the method, right? The method then fills the empty pointer with the address of a device object and I can pass the pointer to the device to other methods.

My question is: Is this the right way to do that? If it is, how do I allocate a new pointer from Java?


Based on the accepted answer, I did this:

Memory p = new Memory(Pointer.SIZE);
Memory p2 = new Memory(Pointer.SIZE);
p.setPointer(0, p2);
nativeLib.open_device(ctx, p, index);
return p2;
thejh
  • 44,854
  • 16
  • 96
  • 107
  • Just curious: did your updated code work for you? It seems as though you are setting `*p = p2` but then the C function would do `*p = pdev` thus overwriting the value. – casablanca Nov 28 '10 at 15:38
  • @casablanca: Yes, I tested it, it works. – thejh Nov 28 '10 at 19:58
  • @thejh do you know how to handle the invalidMemoryAccess Exception created because of invalid memory addresses being pointed to? – AnOldSoul Nov 12 '15 at 05:55

3 Answers3

9

It appears that the JNA Pointer class has setPointer and getPointer methods to allow for multiple indirection, and the Memory class to actually "allocate" native objects. So you should be able to do something like: (I'm just guessing from the JNA docs, I've not tested this)

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
Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
casablanca
  • 69,683
  • 7
  • 133
  • 150
0

Even better answer. You may want to allocate (malloc etc) depending upon Java String length. Example below is unit test from JNA project.

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));
}
Ashish Jain
  • 329
  • 2
  • 5
  • 13
-1

There are no pointers in Java, only references.

You cannot reassign a reference when you pass them to methods, because you pass them by value. Everything is passed by value in Java.

You can rewrite this method to instantiate a new instance of the device and return that instead of an int.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 3
    @duffymo: I was talking about JNA Pointers: https://jna.dev.java.net/javadoc/com/sun/jna/Pointer.html – thejh Nov 27 '10 at 22:36
  • It's possible to do this without JNA. You just have to return the new reference to the Device object you instantiate instead of an int. – duffymo Nov 27 '10 at 22:52
  • 2
    @duffymo: And how can I access a c library (libbla.so) using Java without this explicitly native stuff? – thejh Nov 27 '10 at 22:54
  • @duffymo: In Java, references *can* be null, and they can be re-assigned. You're thinking of C++. Also, when interacting with native code, it is common to use Java objects to represent native pointers. – Andy Thomas Dec 09 '10 at 15:02
  • You're right Andy, now I realize that I was thinking of C++. I've corrected my answer. – duffymo Dec 09 '10 at 15:21
  • @Andy - After thinking about it some more, I think I was mixing my languages during the discussion. I know that Java references can be null and C++ cannot. If the OP is trying to simulate pointers or references in C++ using Java those issues will have to be taken into consideration. I didn't write it well. – duffymo Dec 09 '10 at 18:35