summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/manual/example1/function.c3
-rw-r--r--doc/manual/example1/function.cfg5
-rw-r--r--doc/manual/example1/function.h1
-rw-r--r--doc/manual/example1/gen.sh17
-rw-r--r--doc/manual/example2/function.c17
-rw-r--r--doc/manual/example2/function.cfg9
-rw-r--r--doc/manual/example2/function.h3
-rw-r--r--doc/manual/example2/gen.sh17
-rw-r--r--doc/manual/example3/function.cfg16
-rw-r--r--doc/manual/example3/function.h5
-rw-r--r--doc/manual/example3/gen.sh17
-rw-r--r--doc/manual/example4/function.c10
-rw-r--r--doc/manual/example4/function.cfg12
-rw-r--r--doc/manual/example4/function.h2
-rw-r--r--doc/manual/example4/gen.sh17
-rw-r--r--doc/manual/example5/function.c16
-rw-r--r--doc/manual/example5/function.cfg9
-rw-r--r--doc/manual/example5/function.h8
-rw-r--r--doc/manual/example5/gen.sh17
-rwxr-xr-xdoc/manual/index.html371
20 files changed, 569 insertions, 3 deletions
diff --git a/doc/manual/example1/function.c b/doc/manual/example1/function.c
new file mode 100644
index 0000000..9a84189
--- /dev/null
+++ b/doc/manual/example1/function.c
@@ -0,0 +1,3 @@
+int one_plus(int a) {
+ return 1 + a;
+}
diff --git a/doc/manual/example1/function.cfg b/doc/manual/example1/function.cfg
new file mode 100644
index 0000000..c604a40
--- /dev/null
+++ b/doc/manual/example1/function.cfg
@@ -0,0 +1,5 @@
+Package testfunction
+Style AllStatic
+JavaClass TestFunction
+JavaOutputDir gensrc/java
+NativeOutputDir gensrc/native
diff --git a/doc/manual/example1/function.h b/doc/manual/example1/function.h
new file mode 100644
index 0000000..58976c1
--- /dev/null
+++ b/doc/manual/example1/function.h
@@ -0,0 +1 @@
+int one_plus(int a);
diff --git a/doc/manual/example1/gen.sh b/doc/manual/example1/gen.sh
new file mode 100644
index 0000000..6fb971e
--- /dev/null
+++ b/doc/manual/example1/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/example2/function.c b/doc/manual/example2/function.c
new file mode 100644
index 0000000..159ddb7
--- /dev/null
+++ b/doc/manual/example2/function.c
@@ -0,0 +1,17 @@
+float process_data(float* data, int n) {
+ int i;
+ float sum;
+ for (i = 0; i < n; i++) {
+ sum += data[i];
+ }
+ return sum;
+}
+
+float* global_data;
+void set_global_data(float* data) {
+ global_data = data;
+}
+
+float process_global_data(int n) {
+ return process_data(global_data, n);
+}
diff --git a/doc/manual/example2/function.cfg b/doc/manual/example2/function.cfg
new file mode 100644
index 0000000..91d379b
--- /dev/null
+++ b/doc/manual/example2/function.cfg
@@ -0,0 +1,9 @@
+Package testfunction
+Style AllStatic
+JavaClass TestFunction
+JavaOutputDir gensrc/java
+NativeOutputDir gensrc/native
+
+# The semantics of set_global_data imply that
+# only direct Buffers are legal
+NioDirectOnly set_global_data
diff --git a/doc/manual/example2/function.h b/doc/manual/example2/function.h
new file mode 100644
index 0000000..af14bd2
--- /dev/null
+++ b/doc/manual/example2/function.h
@@ -0,0 +1,3 @@
+float process_data(float* data, int n);
+void set_global_data(float* data);
+float process_global_data(int n);
diff --git a/doc/manual/example2/gen.sh b/doc/manual/example2/gen.sh
new file mode 100644
index 0000000..3310b06
--- /dev/null
+++ b/doc/manual/example2/gen.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+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/example3/function.cfg b/doc/manual/example3/function.cfg
new file mode 100644
index 0000000..8ac334f
--- /dev/null
+++ b/doc/manual/example3/function.cfg
@@ -0,0 +1,16 @@
+Package testfunction
+Style AllStatic
+JavaClass TestFunction
+JavaOutputDir gensrc/java
+NativeOutputDir gensrc/native
+
+# strlen takes a string as argument
+ArgumentIsString strlen 0
+
+# strstr takes strings as arguments
+ArgumentIsString strstr 0 1
+# it also returns a string
+ReturnsString strstr
+
+CustomCCode /* Include string.h header */
+CustomCCode #include <string.h>
diff --git a/doc/manual/example3/function.h b/doc/manual/example3/function.h
new file mode 100644
index 0000000..31ee673
--- /dev/null
+++ b/doc/manual/example3/function.h
@@ -0,0 +1,5 @@
+/* Give GlueGen a typedef for size_t */
+typedef int size_t;
+
+size_t strlen(const char* str);
+char* strstr(const char* str1, const char* str2);
diff --git a/doc/manual/example3/gen.sh b/doc/manual/example3/gen.sh
new file mode 100644
index 0000000..6fb971e
--- /dev/null
+++ b/doc/manual/example3/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/example4/function.c b/doc/manual/example4/function.c
new file mode 100644
index 0000000..8666666
--- /dev/null
+++ b/doc/manual/example4/function.c
@@ -0,0 +1,10 @@
+#include <stdlib.h>
+#include <malloc.h>
+
+void* custom_allocate(int num_bytes) {
+ return malloc(num_bytes);
+}
+
+void custom_free(void* data) {
+ free(data);
+}
diff --git a/doc/manual/example4/function.cfg b/doc/manual/example4/function.cfg
new file mode 100644
index 0000000..feee635
--- /dev/null
+++ b/doc/manual/example4/function.cfg
@@ -0,0 +1,12 @@
+Package testfunction
+Style AllStatic
+JavaClass TestFunction
+JavaOutputDir gensrc/java
+NativeOutputDir gensrc/native
+
+# The length of the returned ByteBuffer from custom_allocate is
+# specified as the argument
+ReturnValueCapacity custom_allocate {0}
+
+# custom_free will only ever receive a direct Buffer
+NioDirectOnly custom_free
diff --git a/doc/manual/example4/function.h b/doc/manual/example4/function.h
new file mode 100644
index 0000000..8db77a1
--- /dev/null
+++ b/doc/manual/example4/function.h
@@ -0,0 +1,2 @@
+void* custom_allocate(int num_bytes);
+void custom_free(void* data);
diff --git a/doc/manual/example4/gen.sh b/doc/manual/example4/gen.sh
new file mode 100644
index 0000000..6fb971e
--- /dev/null
+++ b/doc/manual/example4/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/example5/function.c b/doc/manual/example5/function.c
new file mode 100644
index 0000000..457b4a4
--- /dev/null
+++ b/doc/manual/example5/function.c
@@ -0,0 +1,16 @@
+static ScreenInfo default;
+static int initialized = 0;
+
+ScreenInfo* default_screen_depth() {
+ if (!initialized) {
+ default.redBits = 8;
+ default.greenBits = 8;
+ default.blueBits = 8;
+ initialized = 1;
+ }
+ return &default;
+}
+
+void set_screen_depth(ScreenInfo* info) {
+ /* Do something ... */
+}
diff --git a/doc/manual/example5/function.cfg b/doc/manual/example5/function.cfg
new file mode 100644
index 0000000..cb158ca
--- /dev/null
+++ b/doc/manual/example5/function.cfg
@@ -0,0 +1,9 @@
+Package testfunction
+Style AllStatic
+JavaClass TestFunction
+JavaOutputDir gensrc/java
+NativeOutputDir gensrc/native
+
+# Tell GlueGen that default_screen_depth() returns a pointer to a
+# single ScreenInfo
+ReturnValueCapacity default_screen_depth sizeof(ScreenInfo)
diff --git a/doc/manual/example5/function.h b/doc/manual/example5/function.h
new file mode 100644
index 0000000..d845887
--- /dev/null
+++ b/doc/manual/example5/function.h
@@ -0,0 +1,8 @@
+typedef struct {
+ int redBits;
+ int greenBits;
+ int blueBits;
+} ScreenInfo;
+
+ScreenInfo* default_screen_depth();
+void set_screen_depth(ScreenInfo* info);
diff --git a/doc/manual/example5/gen.sh b/doc/manual/example5/gen.sh
new file mode 100644
index 0000000..6fb971e
--- /dev/null
+++ b/doc/manual/example5/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 cbeea8e..e2e0fbc 100755
--- a/doc/manual/index.html
+++ b/doc/manual/index.html
@@ -38,11 +38,19 @@ Chapter 2 - Using GlueGen
</UL>
Chapter 3 - Configuration File Examples<BR>
+<UL>
+<LI> <a href = "#SecSimplest">Simplest possible example</a>
+<LI> <a href = "#SecArrays">Arrays and buffers</a>
+<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> More...
</UL>
<H2> Chapter 1 - Introduction </H2>
@@ -1290,8 +1298,11 @@ and TemporaryCVariableAssignment directives.
(optional) Indicates that the specified C function which returns a
<code>char*</code> or compatible type actually returns a
null-terminated C string which should be exposed as a
-java.lang.String.
-
+java.lang.String. NOTE: currently does not properly handle the case
+where this storage needs to be freed by the end user. In these
+situations the data should be returned as a direct ByteBuffer, the
+ByteBuffer converted to a String using custom Java code, and the
+ByteBuffer freed manually using another function bound to Java.
<dt><strong><a name="ReturnValueCapacity">ReturnValueCapacity</a></strong>
<dd> Syntax: <code>ReturnValueCapacity [C function name]
@@ -1606,5 +1617,359 @@ the header.
</dl>
+<H2> Chapter 3 - Configuration File Examples </H2>
+
+<H3><a name="SecSimplest">Simplest possible example</a></H3>
+
+Files:
+<UL>
+<LI> <a href="example1/function.c">function.c</a>
+<LI> <a href="example1/function.h">function.h</a>
+<LI> <a href="example1/function.cfg">function.cfg</a>
+<LI> <a href="example1/gen.sh">gen.sh</a>
+</UL>
+
+<P> This example shows the simplest possible usage of GlueGen; a
+single routine taking as arguments and returning only primitive
+types. The signature of the C function we are interested in binding is
+</P>
+
+<PRE>
+ int one_plus(int a);
+</PRE>
+
+<P> To bind this function to Java, we only need a configuration file
+with very basic settings, indicating the style of glue code emission,
+the package and class into which the glue code will be generated, and
+the output directories for the Java and native code. The contents of
+the configuration file are as follows: </P>
+
+<PRE>
+ Package testfunction
+ Style AllStatic
+ JavaClass TestFunction
+ JavaOutputDir gensrc/java
+ NativeOutputDir gensrc/native
+</PRE>
+
+<P> GlueGen can then be invoked with approximately the following
+command line: </P>
+
+<PRE>
+ java -cp gluegen.jar:antlr.jar com.sun.gluegen.GlueGen \
+ -I. -Ecom.sun.gluegen.JavaEmitter -Cfunction.cfg function.h
+</PRE>
+
+<P> The resulting Java and native code needs to be compiled, and the
+application needs to load the native library for the Java binding
+before attempting to invoke the native method by calling
+<CODE>System.load()</CODE> or <CODE>System.loadLibrary()</CODE>. </P>
+
+<H3><a name="SecArrays">Arrays and buffers</a></H3>
+
+Files:
+<UL>
+<LI> <a href="example2/function.c">function.c</a>
+<LI> <a href="example2/function.h">function.h</a>
+<LI> <a href="example2/function.cfg">function.cfg</a>
+<LI> <a href="example2/gen.sh">gen.sh</a>
+</UL>
+
+<P> This example shows how C primitive arrays are bound to Java. The
+header file contains three functions to bind: </P>
+
+<PRE>
+ float process_data(float* data, int n);
+ void set_global_data(float* data);
+ float process_global_data(int n);
+</PRE>
+
+<P> The semantics of <CODE>process_data</CODE> are that it takes in a
+pointer to a set of primitive <CODE>float</CODE> values and the number
+of elements in the array and performs some operation on them,
+returning a floating-point value as the result. Afterward the passed
+data is no longer referenced. </P>
+
+<P> <CODE>set_global_data</CODE>, on the other hand, takes a pointer
+to the data and stores it persistently in the C code.
+<CODE>process_global_data</CODE> then accepts as argument the number
+of elements to process from the previously-set global data, performs
+this processing and returns a result. The global data may be accessed
+again afterward. As an example, these kinds of semantics are used in
+certain places in the OpenGL API. </P>
+
+<P> From a Java binding standpoint, <CODE>process_data</CODE> may
+accept data stored either inside the Java heap (in the form of a
+<CODE>float[]</CODE> or non-direct <CODE>FloatBuffer</CODE>) or
+outside the Java heap (in the form of a direct
+<CODE>FloatBuffer</CODE>), because it does not access the data after
+the function call has completed and therefore would not be affected if
+garbage collection moved the data after the function call was
+complete. However, <CODE>set_global_data</CODE> can cause the passed
+data to be accessed after the function call is complete, if
+<CODE>process_global_data</CODE> is called. Therefore the data passed
+to <CODE>set_global_data</CODE> may not reside in the Java
+garbage-collected heap, but must reside outside the heap in the form
+of a direct <CODE>FloatBuffer</CODE>. </P>
+
+<P> It is straightforward to take into account these differences in
+semantics in the configuration file using the <a
+href="#NioDirectOnly">NioDirectOnly</a> directive: </P>
+
+<PRE>
+ # The semantics of set_global_data imply that
+ # only direct Buffers are legal
+ NioDirectOnly set_global_data
+</PRE>
+
+<P> Note the differences in the generated Java-side overloadings for
+the two functions: </P>
+
+<PRE>
+ public static void process_data(java.nio.FloatBuffer data, int n) {...}
+ public static void process_data(float[] data, int data_offset, int n) {...}
+ public static void set_global_data(java.nio.FloatBuffer data) {...}
+</PRE>
+
+<P> No overloading is produced for <CODE>set_global_data</CODE> taking
+a <CODE>float[]</CODE>, as it can not handle data residing in the Java
+heap. Further, the generated glue code will verify that any
+<CODE>FloatBuffer</CODE> passed to this routine is direct, throwing a
+<CODE>RuntimeException</CODE> if not. The type of the exception thrown
+in this and other cases may be changed with the <a
+href="#RuntimeExceptionType">RuntimeExceptionType</a> directive.
+
+<H3><a name="SecString">String handling</a></H3>
+
+Files:
+<UL>
+<LI> <a href="example3/function.h">function.h</a>
+<LI> <a href="example3/function.cfg">function.cfg</a>
+<LI> <a href="example3/gen.sh">gen.sh</a>
+</UL>
+
+<P> This example shows how to pass and return C strings. The functions
+involved are a bit contrived, as nobody would ever need to bind the C
+library's string handling routines to Java, but they do illustrate
+situations in which Java strings might need to be passed to C and C
+strings returned to Java. As an example, both styles of function are
+present in the OpenGL and OpenAL APIs. </P>
+
+<P> The included source code exposes two functions to Java: </P>
+
+<PRE>
+ size_t strlen(const char* str);
+ char* strstr(const char* str1, const char* str2);
+</PRE>
+
+<P> Note that we might just as easily parse the C standard library's
+<CODE>string.h</CODE> header file to pick up these function
+declarations. However for the purposes of this example it is easier to
+extract just the functions we need. </P>
+
+<P> Note that the <a href="example3/function.h">function.h</a> header
+file contains a typedef for <CODE>size_t</CODE>. This is needed
+because GlueGen does not inherently know about this data type. An
+equivalent data type for the purposes of this example is
+<CODE>int</CODE>, so we choose to tell GlueGen to use that data type
+in place of <CODE>size_t</CODE> while generating glue code. </P>
+
+<P> The following directive in the configuration file tells GlueGen
+that <CODE>strlen</CODE> takes a string as argument 0 (the first
+argument): </P>
+
+<PRE>
+ ArgumentIsString strlen 0
+</PRE>
+
+<P> The following directive tells GlueGen that <CODE>strstr</CODE>
+takes two strings as its arguments: </P>
+
+<PRE>
+ ArgumentIsString strstr 0 1
+</PRE>
+
+<P> Finally, the following directive tells GlueGen that
+<CODE>strstr</CODE> returns a string instead of an array of bytes:
+</P>
+
+<PRE>
+ ReturnsString strstr
+</PRE>
+
+<P> We also use the <a href="#CustomCCode">CustomCCode</a> directive
+to cause the <CODE>string.h</CODE> header file to be #included in the
+generated glue code: </P>
+
+<PRE>
+ CustomCCode /* Include string.h header */
+ CustomCCode #include &lt;string.h&gt;
+</PRE>
+
+<P> Now the bindings of these two functions to Java look as expected:
+<P>
+
+<PRE>
+ public static native int strlen(java.lang.String str);
+ public static native java.lang.String strstr(java.lang.String str1,
+ java.lang.String str2);
+</PRE>
+
+Note that the <a href="#ReturnsString">ReturnsString</a> directive
+does not currently correctly handle the case where the
+<CODE>char*</CODE> returned from C needs to be explicitly freed. As an
+example, a binding of the C function <CODE>strdup</CODE> using a
+ReturnsString directive would cause a C heap memory leak.
+
+<H3><a name="SecMemory">Memory allocation</a></H3>
+
+Files:
+<UL>
+<LI> <a href="example4/function.c">function.c</a>
+<LI> <a href="example4/function.h">function.h</a>
+<LI> <a href="example4/function.cfg">function.cfg</a>
+<LI> <a href="example4/gen.sh">gen.sh</a>
+</UL>
+
+<P> This example shows how memory allocation is handled when binding C
+to Java. It gives the example of a custom memory allocator being bound
+to Java; this is a construct that at least at one point was present in
+OpenGL in the NV_vertex_array_range extension. </P>
+
+<P> The two functions we are exposing to Java are as follows: </P>
+<PRE>
+ void* custom_allocate(int num_bytes);
+ void custom_free(void* data);
+</PRE>
+
+<P> The Java-side return type of <CODE>custom_allocate</CODE> will
+necessarily be a <CODE>ByteBuffer</CODE>, as that is the only useful
+way of interacting with arbitrary memory produced by C. The question
+is how to inform the glue code generator of the size of the returned
+sequence of memory. The semantics of <CODE>custom_allocate</CODE> are
+obvious to the programmer; the incoming <CODE>num_bytes</CODE>
+argument specifies the amount of returned memory. We tell GlueGen this
+fact using the <a href="#ReturnValueCapacity">ReturnValueCapacity</a>
+directive: </P>
+
+<PRE>
+ # The length of the returned ByteBuffer from custom_allocate is
+ # specified as the argument
+ ReturnValueCapacity custom_allocate {0}
+</PRE>
+
+<P> Note that we name incoming argument 0 with the MessageFormat
+specifier "{0}" rather than the explicit name of the parameter
+("num_bytes") for generality, in case the header file is changed
+later. </P>
+
+<P> Because <CODE>custom_free</CODE> will only ever receive Buffers
+produced by custom_allocate, we use the <a
+href="#NioDirectOnly">NioDirectOnly</a> directive to prevent
+accidental usage with the wrong kind of Buffer: </P>
+
+<PRE>
+ # custom_free will only ever receive a direct Buffer
+ NioDirectOnly custom_free
+</PRE>
+
+<P> The generated Java APIs for these functions are as follows: </P>
+
+<PRE>
+ public static java.nio.ByteBuffer custom_allocate(int num_bytes) {...}
+ public static void custom_free(java.nio.Buffer data) {...}
+</PRE>
+
+<H3><a name="SecStructs">Ingoing and outgoing structs</a></H3>
+
+Files:
+<UL>
+<LI> <a href="example5/function.c">function.c</a>
+<LI> <a href="example5/function.h">function.h</a>
+<LI> <a href="example5/function.cfg">function.cfg</a>
+<LI> <a href="example5/gen.sh">gen.sh</a>
+</UL>
+
+<P> This example shows how GlueGen provides access to C structs and
+supports both passing them to and returning them from C functions. The
+header file defines a sample data structure that might describe the
+bit depth of a given screen: </P>
+
+<PRE>
+ typedef struct {
+ int redBits;
+ int greenBits;
+ int blueBits;
+ } ScreenInfo;
+</PRE>
+
+<P> Two functions are defined which take and return this data type:
+</P>
+
+<PRE>
+ ScreenInfo* default_screen_depth();
+ void set_screen_depth(ScreenInfo* info);
+</PRE>
+
+<P> The semantics of <CODE>default_screen_depth()</CODE> are that it
+returns a pointer to some static storage which does not need to be
+freed, which describes the default screen depth.
+<CODE>set_screen_depth()</CODE> is a hypothetical function which would
+take a newly-allocated <CODE>ScreenInfo</CODE> and cause the primary
+display to switch to the specified bit depth. </P>
+
+<P> The only additional information we need to tell GlueGen, beyond
+that in the header file, is how much storage is returned from
+<CODE>default_screen_depth()</CODE>. Note the semantic ambiguity,
+where it might return a pointer to a single <CODE>ScreenInfo</CODE> or
+a pointer to an array of <CODE>ScreenInfo</CODE>s. We tell GlueGen
+that the return value is a single value with the <a
+href="#ReturnValueCapacity">ReturnValueCapacity</a> directive,
+similarly to the <a href="#SecMemory">memory allocation</a> example
+above: </P>
+
+<PRE>
+ # Tell GlueGen that default_screen_depth() returns a pointer to a
+ # single ScreenInfo
+ ReturnValueCapacity default_screen_depth sizeof(ScreenInfo)
+</PRE>
+
+<P> Note that if <CODE>default_screen_depth</CODE> had returned
+newly-allocated storage, it would be up to the user to expose a
+<CODE>free()</CODE> function to Java and call it when necessary. </P>
+
+<P> GlueGen automatically generates a Java-side
+<CODE>ScreenInfo</CODE> class which supports not only access to any
+such objects returned from C, but also allocation of new
+<CODE>ScreenInfo</CODE> structs which can be passed (persistently)
+down to C. The Java API for the ScreenInfo class looks like this: </P>
+
+<PRE>
+ public abstract class ScreenInfo {
+ public static ScreenInfo create();
+ public abstract ScreenInfo redBits(int val);
+ public abstract int redBits();
+ ...
+ }
+</PRE>
+
+<P> The <CODE>create()</CODE> method allocates a new ScreenInfo struct
+which may be passed, even persistently, out to C. Its C-heap storage
+will be automatically reclaimed when the Java-side ScreenInfo object
+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>
+
+
+
+
+
+
+
+
+
+
+
+
</BODY>
</HTML>