Posted by
Sven Gothel on
Nov 30, 2011; 1:08pm
URL: https://forum.jogamp.org/binding-a-C-functions-that-allocates-two-chunks-of-memory-and-returns-an-integer-tp3547863p3548229.html
On Wednesday, November 30, 2011 11:23:46 AM a001 [via jogamp] wrote:
>
> Thanks for all the great work with JogAmp and GlueGen.
>
> I have a C library (to be called from Java) and I would be happy to use
> GlueGen to automate the generation of the necessary Java and JNI code.
>
> However, after looking to the GlueGen manual, I'm afraid I'm still missing
> something. I've noticed the examples you provide about how to manage ingoing
> and outgoing structs, array of structs, and array of pointers. They are
> great.
>
> Still, I have not understood how to bind API like the following:
>
> struct foo_s; /* forward decl */
> typedef struct foo_s foo_t;
>
> int foo(foo_t **a, foo_t **b);
>
> foo allocates two variables of type foo_t and places the addresses of
> allocated memory respectively in *a and *b. Returns zero on success, or one
> of the applicable error values on failure.
>
> Please, can you tell me how to generate the glue code for this?
Since 'struct foo_s' is opaque, ie. a 'void *', it shall be opaque for GlueGen as well.
Your 2 arguments refer to a _writable_ pointer array of these opaque type,
hence the PointerType shall be generated.
We have similar tests in GlueGen's unit tests, and it works quite well, eg:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/test1.h;hb=HEAD 30 typedef uint64_t foo; // similar to your 'struct foo' if opaque
44 /** Returns a copy of the passed array, each element incr by 1 */
45 MYAPI foo * MYAPIENTRY arrayTestFoo2(const foo * array );
46
47 /** Increments each element of the passed array by 1 - IDENTITY */
48 MYAPI void MYAPIENTRY arrayTestFoo3(foo * array );
49
50 /** Returns a array-array of the passed array, split at ARRAY size - IDENTITY! */
51 MYAPI foo * * MYAPIENTRY arrayTestFoo3ArrayToPtrPtr(const foo * array);
52
53 /** Fills dest array ptr of ARRAY size with arrays (allocs) and copies content of src to it - COPY! */
54 MYAPI void MYAPIENTRY arrayTestFoo3CopyPtrPtrA(foo * * dest, const foo * * src);
A 'mapped' structure w/ an anonymous / opaque type here:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/test1.h;hb=HEAD#l132The configuration here:
Dynamic (function lookup, library loading at runtime) - RECOMMENDED:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/test1p2-gluegen.cfg;hb=HEAD Static:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/test1p1-gluegen.cfg;hb=HEAD Base:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg;hb=HEADNote the return size definition in test1-common.cfg:
11 ReturnValueCapacity arrayTestFoo2 ARRAY_SIZE * sizeof(foo)
12 ReturnValueCapacity arrayTestFoo3ArrayToPtrPtr ARRAY_SIZE * sizeof(foo *)
13 ReturnValueCapacity arrayTestFoo3PtrPtr ARRAY_SIZE * sizeof(foo *)
14 ReturnValueCapacity typeTestAnonPointer ARRAY_SIZE * sizeof(MYAPIConfig)
GlueGen generates:
/** Interface to C language function: <br> <code> foo * arrayTestFoo2(const foo * array); </code> */
public LongBuffer arrayTestFoo2(LongBuffer array);
/** Interface to C language function: <br> <code> foo * arrayTestFoo2(const foo * array); </code> */
public LongBuffer arrayTestFoo2(long[] array, int array_offset);
/** Interface to C language function: <br> <code> void arrayTestFoo3(foo * array); </code> */
public void arrayTestFoo3(LongBuffer array);
/** Interface to C language function: <br> <code> void arrayTestFoo3(foo * array); </code> */
public void arrayTestFoo3(long[] array, int array_offset);
/** Interface to C language function: <br> <code> foo * * arrayTestFoo3ArrayToPtrPtr(const foo * array); </code> */
public PointerBuffer arrayTestFoo3ArrayToPtrPtr(LongBuffer array);
/** Interface to C language function: <br> <code> foo * * arrayTestFoo3ArrayToPtrPtr(const foo * array); </code> */
public PointerBuffer arrayTestFoo3ArrayToPtrPtr(long[] array, int array_offset);
/** Interface to C language function: <br> <code> void arrayTestFoo3CopyPtrPtrA(foo * * dest, const foo * * src); </code> */
public void arrayTestFoo3CopyPtrPtrA(PointerBuffer dest, PointerBuffer src);
/** Interface to C language function: <br> <code> foo * * arrayTestFoo3PtrPtr(foo * * array); </code> */
public PointerBuffer arrayTestFoo3PtrPtr(PointerBuffer array);
The tests for above bindings is here:
http://jogamp.org/git/?p=gluegen.git;a=blob;f=src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java;hb=HEAD#l271>
> In the examples you provide I've noticed that all functions allocating
> memory return a pointer to some static storage and how the
> ReturnValueCapacity directive is used to specify the size of the returned
> memory.
Not 'static storage' it's all dynamic.
The ReturnValueCapacity is described above .. see configuration.
Let's see the Java impl .. :
/** Entry point (through function pointer) to C language function: <br> <code> foo * * arrayTestFoo3ArrayToPtrPtr(const foo * array); </code> */
public PointerBuffer arrayTestFoo3ArrayToPtrPtr(long[] array, int array_offset) {
// REMOVED CHECKS ..
ByteBuffer _res;
_res = dispatch_arrayTestFoo3ArrayToPtrPtr1(array, Buffers.SIZEOF_LONG * array_offset, false, __addr_);
if (_res == null) return null;
Buffers.nativeOrder(_res);
return PointerBuffer.wrap(_res);
}
The native method returns the nio Buffer like this:
return (*env)->NewDirectByteBuffer(env, _res, ARRAY_SIZE * sizeof(foo *));
I hope this elaboration helps a little bit and these unit tests make things a bit more clear.
>
> What if we need to allocate two chunks of memory and return an integer? Do
> we need to hand-write some glue code?
Please provide a proper example, like the unit tests with C header and some API documentation.
Also don't forget to use 'const' whenever you can, to remove the 'write-back' codegen.
>
> Thanks again for GlueGen and I'm looking forward to using it in this
> project.
You are very welcome.
~Sven
>
> Cheers,
> a.