0

Disclaimer: I ignore pretty much everything about C++, so I hope I'm not saying stupid things here, if I am, please feel free to correct me.

As a Java developer, when I want to create a new object, I use a constructor method that will allocate this object in memory and return a handle on it for me, and I will store this handle in a variable, I do it like this.

Foo o = new Foo();

But in C++, I've been given to understand, that despite the fact it is possible to do so

Foo createFoo(){
    Foo f;
    f.doSomething();
    return f;
}

// ...

Foo f = createFoo();

I can also define a handle by myself, and then call a initializer on it that will allocate memory and bind the handle on it, like this:

void initializeFoo(Foo **f){
    f.doSomething();
    return;
}

// ...

Foo f;
initializeFoo(&f);

So my question is, what happens when we want to use those C++ methods in Java, with JNA?

Let's suppose I have the following C++ header:

typedef struct Foo f;

Foo createFoo();
void initializeFoo(Foo **f);

As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure:

public class Foo extends PointerType{

    public Foo(Pointer address) {
        super(address);
    }
    public Foo() {
        super();
    }
}

Using the createFoo method should be pretty easy as well:

public class TestFoo{
    static{
        System.loadLibrary("foolib");
    }

    public static void main(String[] args){
        FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);

        Foo f = lib.createFoo();
    }

Right?

But my question is, how can I use the initializeFoo function??? I suppose I would have to create a Pointer and give it to the function, but how do I create a non NULL pointer in JNA? I tried the following code, but it results in an EXCEPTION_ACCESS_VIOLATION.

public class TestFoo{
    static{
        System.loadLibrary("foolib");
    }

    public static void main(String[] args){
        FooLib lib = (FooLib)Native.loadLibrary("foolib", FooLib.class);

        Foo f = new Foo();
        lib.initializeFoo(f); // EXCEPTION_ACCESS_VIOLATION
        lib.initializeFoo(f.getPointer()); // EXCEPTION_ACCESS_VIOLATION
    }

Any idea?

Thanks!

nbarraille
  • 9,926
  • 14
  • 65
  • 92

2 Answers2

2
Foo f;
initializeFoo(&f);

initializeFoo() does not "allocate memory and bind the handle" for f, as you say. Foo f; creates f and allocates it in memory. initializeFoo() could do something like assign values to f's member properties, and the like, as well as create another Foo object and assign it to f, but it does not do what you say.

On the other hand,

Foo *f;
f = new Foo();

declares a Foo pointer. new allocates memory and creates a Foo object, and assigns the memory location to f (you can think of a pointer as a integer containing an address).

I think you want to learn more about C++ and pointers before you go any further.

Matthew Read
  • 1,365
  • 1
  • 30
  • 50
1

As I don't have any idea on what a Foo is, or what the Foo structure contains, I'm just going to create a JNA PointerType to declare my structure

This makes it impossible to allocate memory for Foo, as you have to know how much memory you need to allocate. For c structures jna needs a java class mirroring the structure or if you at least know its size you can try to use the Memory class which has a ctor taking a size argument.

For c++ structures and classes using c++ features like inheritance this fails since the required memory and layout depends on the compiler and enabled optimisations.

josefx
  • 15,506
  • 6
  • 38
  • 63
  • @josefx: So there is no way I can use my `intializeFoo(Foo **f)` method with JNA if I don't know the Foo structure? – nbarraille Mar 02 '11 at 16:25
  • @josefx: I would try to allocate memory for this structure but I have no way to know its size, it is defined in a proprietary API. I thought I could escape this problem by defining it as a pointer. – nbarraille Mar 02 '11 at 16:39
  • @nathanb if it is defined in a proprietary api then this api either provides a method returning a pointer or has a header file defining the structure of Foo. – josefx Mar 02 '11 at 16:49
  • @josefx No, the API provides none. It only defines the structure as an opaque one: `typedef struct sp_session sp_session;` and there is no method returning a sp_session. sp_sessions are created with this method: `SP_LIBEXPORT(sp_error) sp_session_create(const sp_session_config *config, sp_session **sess);` – nbarraille Mar 02 '11 at 16:53
  • 1
    @nathanb you can try com.sun.jna.ptr.PointerByReference for that and call getValue() to get the resulting Pointer. – josefx Mar 02 '11 at 18:08
  • @josefx I tried this morning, but didn't succeed. How am I suppose to do this? Should my sp_session class extend it instead of PointerType? – nbarraille Mar 02 '11 at 18:13
  • @josefx : It might be possible to do something with Memory(Pointer.SIZE): http://stackoverflow.com/questions/4294264/how-to-obtain-a-new-pointer-in-java – nbarraille Mar 02 '11 at 18:23
  • 1
    @nathanb have you checked the documentation on http://jna.java.net/ it shows examples for PointerByReference. Also you can pass a single element array of sp_session with a non null sp_session value to get the same result. – josefx Mar 02 '11 at 18:29
  • @nathanb I don't think that it will work the way described in the link. The getPointer(0) does not retrive a stored Pointer value as claimed by casablanca. – josefx Mar 02 '11 at 18:40
  • @josefx You are correct. This did the trick. I had to declare my method like this: `int sp_session_create(Pointer cfg, PointerByReference sess)` and call it like this 'lib.sp_session_create(cfg.getPointer(), new PointerByReference());` – nbarraille Mar 02 '11 at 18:42