4 messages in net.java.dev.jna.usersRe: [jna-users] struct vs &struct vs ...
FromSent OnAttachments
bb...@cox.netJul 16, 2007 9:21 am 
Timothy WallJul 16, 2007 11:54 am 
bb...@cox.netJul 17, 2007 4:45 am 
bb...@cox.netJul 17, 2007 4:53 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [jna-users] struct vs &struct vs struct *Actions...
From:Timothy Wall (twal@dev.java.net)
Date:Jul 16, 2007 11:54:50 am
List:net.java.dev.jna.users

On Jul 16, 2007, at 12:21 PM, <bb@cox.net> <bb@cox.net> wrote:

What is the difference between passing a C struct (used as input- only parameter), an address of a C struct (still used as an input- only parameter), and a pointer to struct, partially filled-in, but which will be filled in by the called function?

In almost all C programs, the only difference is whether you pass the structure ("by value") or a pointer to the structure. Usually if you pass the structure by value, changes made by the called function won't be visible to the caller. Structure by value is also not currently supported by JNA, at least not directly, since it's highly dependent on compiler specifics and has a whole host of corner cases that'd be a pain to support, and the usage is not that common.

When the following C is translated into Java+JNA, what does it look like? -----------------C version--------------------------------- struct A { int a1; } struct B { int b1; } struct D { int d1; int d2; } struct C { int n; struct D* ds; } extern int f(struct A a, struct B *b, struct C *c);

Most compilers will usually pass small structs on the stack, assuming they fit in a stack slot. JNA does not explicitly support struct by value (i.e. the first argument).

If you want the latter arguments to be arrays of contiguous structure memory, you can declare Structure[] in the prototype and use Structure.toArray() (after allocating sufficient memory to hold N structures and using useMemory(block) on the first element).

int foo(int len){ struct A a; a.a1 = 1; struct B b; b.b1 = 2; struct D *d; // "d" set later within f(). struct C *c = malloc(sizeof(struct C)); c->n = len; c->ds = malloc(len*sizeof(struct D)); int rv = f(a,&b,c); if (rv != 0) return rv; d = c->ds[1]; return d.d2; } -----------------Java+JNA version--------------------------------- class A extends Structure { public int a1; } class B extends Structure { public int b1; }

class D extends Structure { public int d1; public int d2; }

class C extends Structure { public int n; public D[] ds; public Pointer ds; }

Arrays within a structure are interpreted as being inline memory. If you want a pointer to memory, use Pointer instead, and then either initialize it with Structure.getPointer() or initialize a structure with Structure.useMemory(mystruct.ds).

public interface L extends Library { L INSTANCE = (L)Native.loadLIbrary("L.dll",L.class) int f(A a, B[] b, C[] c);

// First argument depends on compiler conventions int f(..., B b, C c); // Use this if you're passing a single struct int f(..., B[] b, C[] c); // Use this if you're passing a block/ array of struct

}

int foo(int len) { A a = new A(); a.a1 = 1;

B[] b = new B[1]; B[] b = new B[] { new B() }; b[0].b1 = 2;

C[] c = new C[1]; C[] c = new C[] { new C() }; c[0].ds = new D[len];

D d = new D(); d.useMemory(new Memory(len * d.size())); c[0].ds = (D[])d.toArray(new D[len]);

c[0].n = len;

You can pass an uninitialized array of Structure directly to a function and JNA will auto-initialize it for you, but arrays of Structure within a Structure must be explicitly initialized.

int rv = Lib.INSTANCE.f(a, b, c); if (rv != 0) return rv; D d = c[0].ds[1]; return d.d2; }