diff options
author | Kenneth Russel <[email protected]> | 2006-02-26 18:48:26 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2006-02-26 18:48:26 +0000 |
commit | 0192562ce71078ce91cf02458ee92bc4603dc8ad (patch) | |
tree | 020dbae88647ea50021739a69b82a6c27e517129 | |
parent | e24dc9a626d1548f67dc79b8f73c519c392bda33 (diff) |
Added XGetVisualInfo and glXChooseFBConfig examples from JOGL.
Intended initial set of configuration file examples is now complete.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/../svn-server-sync/gluegen/trunk@19 a78bb65f-1512-4460-ba86-f6dc96a7bf27
-rw-r--r-- | doc/manual/example6/function.cfg | 25 | ||||
-rw-r--r-- | doc/manual/example6/function.h | 23 | ||||
-rw-r--r-- | doc/manual/example6/gen.sh | 17 | ||||
-rw-r--r-- | doc/manual/example7/function.cfg | 15 | ||||
-rw-r--r-- | doc/manual/example7/function.h | 5 | ||||
-rw-r--r-- | doc/manual/example7/gen.sh | 17 | ||||
-rwxr-xr-x | doc/manual/index.html | 293 |
7 files changed, 388 insertions, 7 deletions
diff --git a/doc/manual/example6/function.cfg b/doc/manual/example6/function.cfg new file mode 100644 index 0000000..c94e856 --- /dev/null +++ b/doc/manual/example6/function.cfg @@ -0,0 +1,25 @@ +Package testfunction +Style AllStatic +JavaClass TestFunction +JavaOutputDir gensrc/java +NativeOutputDir gensrc/native + +# Get returned array's capacity from XGetVisualInfo to be correct +TemporaryCVariableDeclaration XGetVisualInfo int count; +TemporaryCVariableAssignment XGetVisualInfo count = _ptr3[0]; +ReturnValueCapacity XGetVisualInfo count * sizeof(XVisualInfo) + +# Helper routine to make the ReturnedArrayLength expression below work correctly +CustomJavaCode TestFunction private static int getFirstElement(IntBuffer buf) { return buf.get(buf.position()); } +CustomJavaCode TestFunction private static int getFirstElement(int[] arr, int offset) { return arr[offset]; } +ReturnedArrayLength XGetVisualInfo getFirstElement({3}) + +# We don't need the Display and Visual data structures to be +# explicitly exposed +Opaque long Display * +Opaque long Visual * +# Ignore the empty Display and Visual data structures (though made +# opaque, the references from XVisualInfo and elsewhere are still +# traversed) +Ignore Display +Ignore Visual diff --git a/doc/manual/example6/function.h b/doc/manual/example6/function.h new file mode 100644 index 0000000..0517471 --- /dev/null +++ b/doc/manual/example6/function.h @@ -0,0 +1,23 @@ +typedef struct {} Display; +typedef struct {} Visual; +typedef unsigned long VisualID; + +typedef struct { + Visual *visual; + VisualID visualid; + int screen; + int depth; + int c_class; /* C++ */ + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int colormap_size; + int bits_per_rgb; +} XVisualInfo; + +XVisualInfo *XGetVisualInfo( + Display* /* display */, + long /* vinfo_mask */, + XVisualInfo* /* vinfo_template */, + int* /* nitems_return */ +); diff --git a/doc/manual/example6/gen.sh b/doc/manual/example6/gen.sh new file mode 100644 index 0000000..6fb971e --- /dev/null +++ b/doc/manual/example6/gen.sh @@ -0,0 +1,17 @@ +#!/bin/ksh + +JAVA=java +GLUEGEN_JAR=../../../build/gluegen.jar +ANTLR_JAR=../../../../../ANTLR/antlr-2.7.4/antlr.jar + +NAME=`uname` + +if [ $NAME="Windows*" ] ; then + SEP=\; +elif [ $NAME="CYGWIN*" ] ; then + SEP=\; +else + SEP=: +fi + +java -cp $GLUEGEN_JAR$SEP$ANTLR_JAR com.sun.gluegen.GlueGen -I. -Ecom.sun.gluegen.JavaEmitter -Cfunction.cfg function.h diff --git a/doc/manual/example7/function.cfg b/doc/manual/example7/function.cfg new file mode 100644 index 0000000..2ac8560 --- /dev/null +++ b/doc/manual/example7/function.cfg @@ -0,0 +1,15 @@ +Package testfunction +Style AllStatic +JavaClass TestFunction +JavaOutputDir gensrc/java +NativeOutputDir gensrc/native + +TemporaryCVariableDeclaration glXChooseFBConfig int count; +TemporaryCVariableAssignment glXChooseFBConfig count = _ptr3[0]; +ReturnValueLength glXChooseFBConfig count + +# We don't need the Display data structure to be explicitly exposed +Opaque long Display * +# Ignore the empty Display data structure (though made opaque, the +# reference from glxChooseFBConfig is still traversed) +Ignore Display diff --git a/doc/manual/example7/function.h b/doc/manual/example7/function.h new file mode 100644 index 0000000..2882d2a --- /dev/null +++ b/doc/manual/example7/function.h @@ -0,0 +1,5 @@ +typedef struct {} Display; +typedef struct __GLXFBConfigRec *GLXFBConfig; + +GLXFBConfig *glXChooseFBConfig( Display *dpy, int screen, + const int *attribList, int *nitems ); diff --git a/doc/manual/example7/gen.sh b/doc/manual/example7/gen.sh new file mode 100644 index 0000000..6fb971e --- /dev/null +++ b/doc/manual/example7/gen.sh @@ -0,0 +1,17 @@ +#!/bin/ksh + +JAVA=java +GLUEGEN_JAR=../../../build/gluegen.jar +ANTLR_JAR=../../../../../ANTLR/antlr-2.7.4/antlr.jar + +NAME=`uname` + +if [ $NAME="Windows*" ] ; then + SEP=\; +elif [ $NAME="CYGWIN*" ] ; then + SEP=\; +else + SEP=: +fi + +java -cp $GLUEGEN_JAR$SEP$ANTLR_JAR com.sun.gluegen.GlueGen -I. -Ecom.sun.gluegen.JavaEmitter -Cfunction.cfg function.h diff --git a/doc/manual/index.html b/doc/manual/index.html index e2e0fbc..ec1ff3a 100755 --- a/doc/manual/index.html +++ b/doc/manual/index.html @@ -44,13 +44,8 @@ Chapter 3 - Configuration File Examples<BR> <LI> <a href = "#SecString">String handling</a> <LI> <a href = "#SecMemory">Memory allocation</a> <LI> <a href = "#SecStructs">Ingoing and outgoing structs</a> -</UL> - -TO DO: - -<UL> -<LI> Example with XVisualInfo* return type -<LI> Example with GLXFBConfig* (e.g. glXChooseFBConfig) +<LI> <a href = "#SecStructArrays">Returned arrays of structs</a> +<LI> <a href = "#SecPointerArrays">Returned arrays of pointers</a> </UL> <H2> Chapter 1 - Introduction </H2> @@ -1960,16 +1955,300 @@ is no longer reachable, as it is backed by a direct New I/O <CODE>ByteBuffer</CODE>. The fields of the struct are exposed as methods which supply both getters and setters. </P> +<H3><a name="SecStructArrays">Returned arrays of structs</a></H3> + +Files: +<UL> +<LI> <a href="example6/function.h">function.h</a> +<LI> <a href="example6/function.cfg">function.cfg</a> +<LI> <a href="example6/gen.sh">gen.sh</a> +</UL> + +<P> This example, taken from JOGL's X11 binding, illustrates how to +return an array of structs from C to Java. The +<CODE>XGetVisualInfo</CODE> function from the X library has the +following signature: </P> + +<PRE> + XVisualInfo *XGetVisualInfo( + Display* display, + long vinfo_mask, + XVisualInfo* vinfo_template, + int* nitems_return + ); +</PRE> + +<P> Note that the <CODE>XVisualInfo</CODE> data structure itself +contains many elements, including a pointer to the current visual. We +use the following trick in the header file to cause GlueGen to treat +the <CODE>Display*</CODE> in the above signature as well as the +<CODE>Visual*</CODE> in the <CODE>XVisualInfo</CODE> as opaque +pointers: </P> + +<PRE> + typedef struct {} Display; + typedef struct {} Visual; + typedef unsigned long VisualID; + + typedef struct { + Visual *visual; + VisualID visualid; + int screen; + int depth; + int c_class; /* C++ */ + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int colormap_size; + int bits_per_rgb; + } XVisualInfo; +</PRE> + +<P> <CODE>XGetVisualInfo</CODE> returns all of the available pixel +formats in the form of <CODE>XVisualInfo</CODE>s which match a given +template. <CODE>display</CODE> is the current connection to the X +server. <CODE>vinfo_mask</CODE> indicates which fields from the +template to match against. <CODE>vinfo_template</CODE> is a partially +filled-in <CODE>XVisualInfo</CODE> specifying the characteristics to +match. <CODE>nitems_return</CODE> is a pointer to an integer +indicating how many <CODE>XVisualInfo</CODE>s were returned. The +return value, rather than being a pointer to a single +<CODE>XVisualInfo</CODE>, is a pointer to the start of an array of +<CODE>XVisualInfo</CODE> data structures. </P> + +<P> There are two basic steps to being able to return this array +properly to Java using GlueGen. The first is creating a direct +ByteBuffer of the appropriate size in the autogenerated JNI code. The +second is slicing up this ByteBuffer appropriately in order to return +an <CODE>XVisualInfo[]</CODE> at the Java level. </P> + +<P> In the autogenerated JNI code, after the call to +<CODE>XGetVisualInfo</CODE> is made, the outgoing +<CODE>nitems_return</CODE> value points to the number of elements in +the returned array, which indicates the size of the direct ByteBuffer +which would need to wrap these elements. However, if we look at the +implementation of one of the generated glue code variants for this +method (specifically, the one taking an <CODE>int[]</CODE> as the +third argument), we can see a problem in trying to access this value +in the C code: </P> + +<PRE> +JNIEXPORT jobject JNICALL +Java_testfunction_TestFunction_XGetVisualInfo1__Ljava_nio_ByteBuffer_2JLjava_nio_ByteBuffer_2Ljava_lang_Object_2I( + JNIEnv *env, jclass _unused, jobject arg0, jlong arg1, jobject arg2, jobject arg3, jint arg3_byte_offset) { + ... + int * _ptr3 = NULL; + ... + if (arg3 != NULL) { + _ptr3 = (int *) (((char*) (*env)->GetPrimitiveArrayCritical(env, arg3, NULL)) + arg3_byte_offset); + } + _res = XGetVisualInfo((Display *) _ptr0, (long) arg1, (XVisualInfo *) _ptr2, (int *) _ptr3); + if (arg3 != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, arg3, _ptr3, 0); + } + if (_res == NULL) return NULL; + return (*env)->NewDirectByteBuffer(env, _res, ??? What to put here ???); +} +</PRE> + +<P> Note that at the point of the statement "What to put here?" the +pointer to the storage of the <CODE>int[]</CODE>, <CODE>_ptr3</CODE>, +has already been released via +<CODE>ReleasePrimitiveArrayCritical</CODE>. This means that it may not +be referenced at the point needed in the code. </P> + +<P> To solve this problem we use the <a +href="#TemporaryCVariableDeclaration">TemporaryCVariableDeclaration</a> +and <a +href="#TemporaryCVariableAssignment">TemporaryCVariableAssignment</a> +directives. We want to declare a persistent integer variable down in +the C code and assign the returned array length to that variable +before the primitive array is released. While in order to do this we +unfortunately need to know something about the structure of the +autogenerated JNI code, at least we don't have to hand-edit it +afterward. We add the following directives to the configuration file: </P> + +<PRE> + # Get returned array's capacity from XGetVisualInfo to be correct + TemporaryCVariableDeclaration XGetVisualInfo int count; + TemporaryCVariableAssignment XGetVisualInfo count = _ptr3[0]; +</PRE> + +<P> Now in the autogenerated JNI code the variable "count" will +contain the number of elements in the returned array. We can then +reference this variable in a <a +href="#ReturnValueCapacity">ReturnValueCapacity</a> directive: </P> + +<PRE> + ReturnValueCapacity XGetVisualInfo count * sizeof(XVisualInfo) +</PRE> + +<P> At this point the <CODE>XGetVisualInfo</CODE> binding will return +a Java-side <CODE>XVisualInfo</CODE> object whose backing ByteBuffer +is the correct size. We now have to inform GlueGen that the underlying +ByteBuffer represents not a single <CODE>XGetVisualInfo</CODE> struct, +but an array of them, using the <a +href="#ReturnedArrayLength">ReturnedArrayLength</a> directive. This +conversion is performed on the Java side of the autogenerated code. +Here, the first element of either the passed <CODE>IntBuffer</CODE> or +<CODE>int[]</CODE> contains the number of elements in the returned +array. (Alternatively, we could examine the length of the ByteBuffer +returned from C to Java and divide by +<CODE>XVisualInfo.size()</CODE>.) Because there are two overloadings +produced by GlueGen for this method, if we reference the +<CODE>nitems_return</CODE> argument in a <a +href="#ReturnedArrayLength">ReturnedArrayLength</a> directive, we need +to handle not only the differing data types properly +(<CODE>IntBuffer</CODE> vs. <CODE>int[]</CODE>), but also the fact +that both the integer array and its offset value are substituted for +any reference to the fourth argument. </P> + +<P> To solve this problem, we define a pair of private helper +functions whose purpose is to handle this overloading. </P> + +<PRE> + CustomJavaCode TestFunction private static int getFirstElement(IntBuffer buf) { + CustomJavaCode TestFunction return buf.get(buf.position()); + CustomJavaCode TestFunction } + CustomJavaCode TestFunction private static int getFirstElement(int[] arr, + CustomJavaCode TestFunction int offset) { + CustomJavaCode TestFunction return arr[offset]; + CustomJavaCode TestFunction } +</PRE> + +<P> Now we can simply write for the returned array length: </P> + +<PRE> + ReturnedArrayLength XGetVisualInfo getFirstElement({3}) +</PRE> + +<P> That's all that is necessary. GlueGen will then produce the +following Java-side overloadings for this function: </P> + +<PRE> + public static XVisualInfo[] XGetVisualInfo(Display arg0, + long arg1, + XVisualInfo arg2, + java.nio.IntBuffer arg3); + public static XVisualInfo[] XGetVisualInfo(Display arg0, + long arg1, + XVisualInfo arg2, + int[] arg3, int arg3_offset); +</PRE> + +<P> As it happens, we don't really need the Display and Visual data +structures to be produced; they can be treated as <CODE>long</CODE>s +on the Java side. Therefore we can add the following directives to the +configuration file: </P> + +<PRE> + # We don't need the Display and Visual data structures to be + # explicitly exposed + Opaque long Display * + Opaque long Visual * + # Ignore the empty Display and Visual data structures (though made + # opaque, the references from XVisualInfo and elsewhere are still + # traversed) + Ignore Display + Ignore Visual +</PRE> + +<P> The final generated Java API is the following: </P> +<PRE> + public static XVisualInfo[] XGetVisualInfo(long arg0, + long arg1, + XVisualInfo arg2, + java.nio.IntBuffer arg3); + public static XVisualInfo[] XGetVisualInfo(long arg0, + long arg1, + XVisualInfo arg2, + int[] arg3, int arg3_offset); +</PRE> +<H3><a name="SecPointerArrays">Returned arrays of pointers</a></H3> +Files: +<UL> +<LI> <a href="example7/function.h">function.h</a> +<LI> <a href="example7/function.cfg">function.cfg</a> +<LI> <a href="example7/gen.sh">gen.sh</a> +</UL> +<P> As with the <a href="#SecStructArrays">example above</a>, this +example is taken from JOGL's X11 binding. Here we show how to expose +to Java a C routine returning an array of pointers to a data +structure. </P> +<P> The declaration of the function we are binding is as follows: </P> +<PRE> + typedef struct __GLXFBConfigRec *GLXFBConfig; + GLXFBConfig *glXChooseFBConfig( Display *dpy, int screen, + const int *attribList, int *nitems ); +</PRE> +<P> This function is used during allocation of a hardware-accelerated +off-screen surface ("pbuffer") on X11 platforms; its exact meaning is +not important. The semantics of the arguments and return value are as +follows. As in the <a href="#SecStructArrays">previous example</a>, it +accepts a connection to the current X display as one argument. The +screen of this display is the second argument. The +<CODE>attribList</CODE> is a zero-terminated list of integer +attributes; because it is zero-terminated, the length of this list is +not passed to the function. As in the previous example, the +<CODE>nitems</CODE> argument points to an integer into which the +number of returned <CODE>GLXFBConfig</CODE> objects is placed. The +return value is an array of <CODE>GLXFBConfig</CODE> objects. </P> + +<P> Because the <CODE>GLXFBConfig</CODE> data type is typedefed as a +pointer to an opaque (undefined) struct, the construct +<CODE>GLXFBConfig*</CODE> is implicitly a "pointer-to-pointer" type. +GlueGen automatically assumes this is convertible to a Java-side array +of accessors to structs. The only configuration necessary is to tell +GlueGen the length of this array. </P> + +<P> As in the previous example, we use the <a +href="#TemporaryCVariableDeclaration">TemporaryCVariableDeclaration</a> +and <a +href="#TemporaryCVariableAssignment">TemporaryCVariableAssignment</a> +directives to capture the length of the returned array: </P> +TemporaryCVariableDeclaration glXChooseFBConfig int count; +TemporaryCVariableAssignment glXChooseFBConfig count = _ptr3[0]; + +<P> The structure of the generated glue code for the return value is +subtly different than in the previous example. The question in this +case is not whether the return value is a pointer to a single object +vs. a pointer to an array of objects; it is what the length of the +returned array is, since we already know that the return type is +pointer-to-pointer and is therefore an array. We use the <a +href="#ReturnValueLength">ReturnValueLength</a> directive for this +case: </P> + +<PRE> + ReturnValueLength glXChooseFBConfig count +</PRE> + +We add similar Opaque directives to the previous example to yield the +resulting Java bindings for this function: + +<PRE> + public static GLXFBConfig[] glXChooseFBConfig(long dpy, + int screen, + java.nio.IntBuffer attribList, + java.nio.IntBuffer nitems); + public static GLXFBConfig[] glXChooseFBConfig(long dpy, + int screen, + int[] attribList, int attribList_offset, + int[] nitems, int nitems_offset); +</PRE> +Note that because the GLXFBConfig data type is returned as an element +of an array, we can not use the Opaque directive to erase this data +type to <CODE>long</CODE> as we did with the <CODE>Display</CODE> data +type. </BODY> </HTML> |