cinvoke-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cinvoke-svn] r76 - in trunk/cinvoke/bindings/java: . org/cinvoke


From: will
Subject: [cinvoke-svn] r76 - in trunk/cinvoke/bindings/java: . org/cinvoke
Date: 7 Jul 2006 00:38:41 -0400

Author: will
Date: 2006-07-07 00:38:40 -0400 (Fri, 07 Jul 2006)
New Revision: 76

Modified:
   trunk/cinvoke/bindings/java/Makefile
   trunk/cinvoke/bindings/java/org/cinvoke/CInvProxy.java
   trunk/cinvoke/bindings/java/org/cinvoke/CInvoke.java
   trunk/cinvoke/bindings/java/org/cinvoke/CInvokeError.java
   trunk/cinvoke/bindings/java/org/cinvoke/NativeInt.java
   trunk/cinvoke/bindings/java/org/cinvoke/NativeLong.java
   trunk/cinvoke/bindings/java/org/cinvoke/NativeLongLong.java
   trunk/cinvoke/bindings/java/org/cinvoke/NativeShort.java
   trunk/cinvoke/bindings/java/org/cinvoke/Natives.java
   trunk/cinvoke/bindings/java/org/cinvoke/Ptr.java
Log:
finished up marshaling except for callbacks, added javadoc


Modified: trunk/cinvoke/bindings/java/Makefile
===================================================================
--- trunk/cinvoke/bindings/java/Makefile        2006-07-06 22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/Makefile        2006-07-07 04:38:40 UTC (rev 76)
@@ -23,3 +23,7 @@
 test:
        javac Test.java
        LD_LIBRARY_PATH=. java Test
+
+doc:
+       rm -rf javadoc
+       javadoc -d javadoc org/cinvoke/*.java

Modified: trunk/cinvoke/bindings/java/org/cinvoke/CInvProxy.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/CInvProxy.java      2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/CInvProxy.java      2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,267 +1,93 @@
 package org.cinvoke;
 import java.lang.reflect.*;
-import java.util.*;
 
 class CInvProxy implements InvocationHandler {
-       private long _ctx = 0;
        private long _lib = 0;
        private int _cc;
        private int _encoding;
-       private HashMap _functions;
-       private HashMap _structs;
+       private Natives _n;
 
        public CInvProxy(String libname, int cc, int encoding) {
-               _ctx = Natives.createContext();
-               if (_ctx == 0) throw new OutOfMemoryError();
-               _lib = Natives.createLibrary(_ctx, libname);
+               _n = new Natives();
+               _lib = Natives.createLibrary(_n._ctx, libname);
                if (_lib == 0) {
                        try {
-                               fail();
+                               _n.fail();
                        } finally {
-                               Natives.deleteContext(_ctx);
-                               _ctx = 0;
+                               _n.close();
                        }
                }
 
                _cc = cc;
                _encoding = encoding;
-               _functions = new HashMap();
-               _structs = new HashMap();
        }
 
        protected void finalize() throws Throwable {
-               close();
-       }
-
-       public void close() {
-               for (Iterator i = _functions.values().iterator(); i.hasNext();)
-                       ((NativeMethod)i.next()).close();
-               for (Iterator i = _structs.values().iterator(); i.hasNext();) 
-                       ((NativeStruct)i.next()).close();
-               if (_ctx != 0) {
-                       if (_lib != 0) {
-                               Natives.deleteLibrary(_ctx, _lib);
-                               _lib = 0;
-                       }
-                       Natives.deleteContext(_ctx);
-                       _ctx = 0;
+               if (_lib != 0) {
+                       Natives.deleteLibrary(_n._ctx, _lib);
+                       _lib = 0;
                }
+               _n.close();
        }
 
-       private void fail() {
-               throw new CInvokeError(Natives.getError(_ctx));
-       }
-
-       class NativeStruct {
-               public NativeStruct(long ctx, long st) {
-                       _ctx = ctx;
-                       this.st = st;
-               }
-
-               public void close() {
-                       if (st != 0) {
-                               Natives.deleteStruct(_ctx, st);
-                               st = 0;
-                       }
-               }
-
-               public long st;
-               private long _ctx;
-       }
-
-       class NativeMethod {
-               public NativeMethod(long ctx, long func, long ep, int[] types,
-                       boolean hasret, int rettype) {
-                       this.func = func;
-                       this.ep = ep;
-                       this.types = types;
-                       this.hasret = hasret;
-                       this.rettype = rettype;
-                       _ctx = ctx;
-               }
-
-               public void close() {
-                       if (func != 0) {
-                               Natives.deleteFunction(_ctx, func);
-                               func = 0;
-                       }
-               }
-
-               private long _ctx;
-               public long func;
-               public long ep;
-               public int[] types;
-               public boolean hasret;
-               public int rettype;
-       }
-       
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
-               NativeMethod meth = (NativeMethod)_functions.get(method);
-               if (meth == null) {
-                       meth = createNative(method);
-                       _functions.put(method, meth);
-               }
-               Class returncls = method.getReturnType();
-               if (returncls.equals(Void.TYPE))
-                       returncls = null;
-               Class realretcls = returncls;
-               if (returncls.equals(String.class))
-                       realretcls = Ptr.class;
+               synchronized (_n) {
+                       Natives.NativeMethod meth = 
_n.createNativeMethod(method, _lib,
+                               _cc);
+                       Class returncls = method.getReturnType();
+                       if (returncls.equals(Void.class))
+                               returncls = null;
+                       Class realretcls = returncls;
+                       if (returncls.equals(String.class))
+                               realretcls = Ptr.class;
 
-               Class[] pclasses = method.getParameterTypes();
-               Object[] params = marshalParams(method, pclasses, args);
-               try {
-                       Object ret;
+                       Class[] pclasses = method.getParameterTypes();
+                       Object[] params = marshalParams(method, pclasses, args);
                        try {
-                               ret = Natives.invokeFunction(_ctx, meth.func, 
meth.ep,
-                                       params, meth.types, realretcls, 
meth.rettype);
-                       } catch (Exception ex) {
-                               if (ex.getMessage().equals("invoke failed")) {
-                                       fail();
-                                       return null;
-                               } else
-                                       throw ex;
-                       }
+                               Object ret;
+                               try {
+                                       ret = Natives.invokeFunction(_n._ctx, 
meth.func, meth.ep,
+                                               params, meth.types, realretcls, 
meth.rettype);
+                               } catch (Exception ex) {
+                                       if (ex.getMessage().equals("invoke 
failed")) {
+                                               _n.fail();
+                                               return null;
+                                       } else
+                                               throw ex;
+                               }
 
-                       for (int i = 0; i < pclasses.length; i++) {
-                               if (pclasses[i].isArray()) {
-                                       
unmarshalArray(((Ptr)params[i]).longValue(), args[i],
-                                               pclasses[i].getComponentType());
+                               for (int i = 0; i < pclasses.length; i++) {
+                                       if (pclasses[i].isArray()) {
+                                               
_n.unmarshalArray(((Ptr)params[i]).longValue(), args[i],
+                                                       
pclasses[i].getComponentType());
+                                       }
                                }
-                       }
 
-                       if (returncls != null)
-                               return unmarshalReturnValue(ret, returncls);
-                       else
-                               return null;
-               } finally {
-                       freeParams(method, params, args);
-               }
-       }
-
-       private int gettypeint(Class cls, boolean thrw) {
-               if (cls.isArray()) {
-                       if (cls.isInterface())
-                               throw new CInvokeError("Arrays of callbacks not 
supported");
-                       if (cls.equals(String.class))
-                               throw new CInvokeError("Arrays of strings not 
supported");
-                       return Natives.T_PTR;
-               } else {
-                       if (cls.isInterface())
-                               return Natives.T_PTR;
-                       else if (cls.equals(String.class))
-                               return Natives.T_PTR;
-                       else if (cls.equals(Byte.class))
-                               return Natives.T_CHAR;
-                       else if (cls.equals(Short.class))
-                               return Natives.T_JSHORT;
-                       else if (cls.equals(Integer.class))
-                               return Natives.T_JINT;
-                       else if (cls.equals(Long.class))
-                               return Natives.T_JLONG;
-                       else if (cls.equals(Float.class))
-                               return Natives.T_FLOAT;
-                       else if (cls.equals(Double.class))
-                               return Natives.T_DOUBLE;
-                       else if (cls.equals(NativeShort.class))
-                               return Natives.T_SHORT;
-                       else if (cls.equals(NativeInt.class))
-                               return Natives.T_INT;
-                       else if (cls.equals(NativeLong.class))
-                               return Natives.T_LONG;
-                       else if (cls.equals(NativeLongLong.class))
-                               return Natives.T_EXTRALONG;
-                       else if (cls.equals(Ptr.class))
-                               return Natives.T_PTR;
-                       else {
-                               if (thrw)
-                                       throw new CInvokeError(
-                                       "Passing or returning structures by 
value not supported");
+                               if (returncls != null)
+                                       return unmarshalReturnValue(ret, 
returncls);
                                else
-                                       return STRUCT_TYPE;
+                                       return null;
+                       } finally {
+                               freeParams(method, params, args);
                        }
                }
        }
 
-       private final static int STRUCT_TYPE = -999;
-       
-       private char gettypechar(int type) {
-               switch (type) {
-               case Natives.T_JSHORT:
-                       return '2';
-               case Natives.T_JINT:
-                       return '4';
-               case Natives.T_JLONG:
-                       return '8';
-               case Natives.T_CHAR:
-                       return 'c';
-               case Natives.T_SHORT:
-                       return 's';
-               case Natives.T_INT:
-                       return 'i';
-               case Natives.T_LONG:
-                       return 'l';
-               case Natives.T_EXTRALONG:
-                       return 'e';
-               case Natives.T_FLOAT:
-                       return 'f';
-               case Natives.T_DOUBLE:
-                       return 'd';
-               case Natives.T_PTR:
-                       return 'p';
-               default:
-                       throw new UnknownError("unknown type");
-               }
-       }
-
-       private NativeMethod createNative(Method method) {
-               long ep = Natives.loadEPLibrary(_ctx, _lib, method.getName());
-               if (ep == 0)
-                       fail();
-               StringBuffer retfmt = new StringBuffer();
-               StringBuffer parmfmt = new StringBuffer();
-               boolean hasret = false;
-               int rettype = 0;
-               Class retcls = method.getReturnType();
-               if (!retcls.equals(Void.TYPE)) {
-                       if (retcls.isArray())
-                               throw new CInvokeError("returning arrays not 
supported");
-                       if (retcls.isInterface())
-                               throw new CInvokeError("returning callbacks not 
supported");
-                       hasret = true;
-                       rettype = gettypeint(retcls, true);
-                       retfmt.append(gettypechar(rettype));
-               }
-
-               Class[] pclasses = method.getParameterTypes();
-               int[] types = new int[pclasses.length];
-               for (int i = 0; i < types.length; i++) {
-                       types[i] = gettypeint(pclasses[i], true);
-                       parmfmt.append(gettypechar(types[i]));
-               }
-
-               long func = Natives.createFunction(_ctx, _cc, retfmt.toString(),
-                       parmfmt.toString());
-               if (func == 0)
-                       fail();
-               return new NativeMethod(_ctx, func, ep, types, hasret, rettype);
-       }
-
        private Object[] marshalParams(Method method, Class[] pclasses,
                Object[] rawparams) {
                Object[] ret = new Object[rawparams.length];
 
                for (int i = 0; i < ret.length; i++) {
                        if (pclasses[i].isArray())
-                               ret[i] = 
marshalArray(pclasses[i].getComponentType(),
+                               ret[i] = 
_n.marshalArray(pclasses[i].getComponentType(),
                                                rawparams[i]);
                        else if (pclasses[i].isInterface()) {
                                // XXX create callback
                        } else if (pclasses[i].equals(String.class))
-                               ret[i] = marshalString((String)rawparams[i]);
+                               ret[i] = _n.marshalString((String)rawparams[i], 
_encoding);
                        else
-                               ret[i] = marshalBasic(rawparams[i], 
pclasses[i]);
+                               ret[i] = _n.marshalBasic(rawparams[i], 
pclasses[i]);
                }
 
                return ret;
@@ -280,247 +106,12 @@
                }
        }
 
-       private Object unmarshalString(long p) {
-               if (p == 0) return null;
-               if (_encoding == CInvoke.ENC.UNICODE)
-                       return Natives.ptrToStringUnicode(p, -1);
-               else
-                       return Natives.ptrToStringUTF8(p);
-       }
-
        private Object unmarshalReturnValue(Object ret, Class type) {
                if (type.equals(String.class)) {
                        Ptr p = (Ptr)ret;
-                       return unmarshalString(p.longValue());
+                       return _n.unmarshalString(p.longValue(), _encoding);
                } else
                        return ret;
        }
 
-       private Object unmarshalStruct(long ptr, Class cls) {
-               long st = getNativeStruct(cls).st;
-               Field[] fields = cls.getFields();
-               Object ret;
-
-               try {
-                       ret = cls.newInstance();
-               } catch (IllegalAccessException iae) {
-                       throw new CInvokeError("Cannot create new instance of 
class " +
-                               cls.getName() + " due a security error: " + 
iae.toString());
-               } catch (InstantiationException ie) {
-                       throw new CInvokeError("Cannot create new instance of 
class " +
-                               cls.getName() + " due to error: " + 
ie.toString());
-               }
-               for (int i = 0; i < fields.length; i++) {
-                       Field fld = fields[i];
-                       Class tcls = fld.getType();
-                       Object val;
-                       int type = gettypeint(tcls, false);
-                       if (type == STRUCT_TYPE) {
-                               long p = Natives.getMemberPtrStruct(_ctx, st, 
ptr,
-                                       fld.getName());
-                               if (p == 0) fail();
-                               val = unmarshalStruct(p, tcls);
-                       } else {
-                               val = Natives.getMemberValueStruct(_ctx, st, 
ptr,
-                                       fld.getName(), tcls, type);
-                       }
-                       try {
-                               fld.set(ret, val);
-                       } catch (IllegalAccessException iae) {
-                               throw new CInvokeError(cls.getName() +
-                                       " field access failed: " + 
iae.toString());
-                       }
-               }
-               
-               return ret;
-       }
-
-       private long marshalStruct(long outp, Object s, Class cls) {
-               if (s == null)
-                       throw new CInvokeError("Invalid null value");
-
-               long st = getNativeStruct(cls).st;
-               Field[] fields = cls.getFields();
-               for (int i = 0; i < fields.length; i++) {
-                       Field fld = fields[i];
-                       Class tcls = fld.getType();
-                       Object val;
-                       try {
-                               val = fld.get(s);
-                       } catch (IllegalAccessException iae) {
-                               throw new CInvokeError(cls.getName() +
-                                       " field access failed: " + 
iae.toString());
-                       }
-                       int type = gettypeint(tcls, false);
-                       if (type == STRUCT_TYPE) {
-                               long p = Natives.getMemberPtrStruct(_ctx, st,
-                                       outp, fld.getName());
-                               if (p == 0) fail();
-                               marshalStruct(p, val, tcls);
-                       } else {
-                               if (Natives.setMemberValueStruct(_ctx, st, outp,
-                                       fld.getName(), val, type) == 0)
-                                       fail();
-                       }
-               }
-
-               int sz = Natives.sizeStruct(_ctx, st);
-               if (sz == -1) fail();
-               return outp + sz;
-       }
-
-       private Object marshalBasic(Object o, Class cls) {
-               if (o == null) {
-                       if (cls.equals(Ptr.class))
-                               return new Ptr(0);
-                       else
-                               throw new CInvokeError("Invalid null value");
-               } else
-                       return o;
-       }
-
-       private Ptr marshalString(String str) {
-               if (str == null) return new Ptr(0);
-
-               long l;
-               if (_encoding == CInvoke.ENC.UNICODE)
-                       l = Natives.stringToPtrUnicode(str);
-               else 
-                       l = Natives.stringToPtrUTF8(str);
-               if (l == 0)
-                       throw new OutOfMemoryError();
-               return new Ptr(l);
-       }
-
-       private Ptr marshalArray(Class eltype, Object val) {
-               if (val == null) return new Ptr(0);
-
-               int numels = Array.getLength(val);
-               int len = numels * sizeof(eltype);
-               
-               long ret = Natives.alloc(len);
-               if (ret == 0)
-                       throw new OutOfMemoryError();
-               
-               int itype = gettypeint(eltype, false);
-
-               long r = ret;
-               for (int i = 0; i < numels; i++) {
-                       Object o = Array.get(val, i);
-                       if (itype == -909)
-                               r = marshalStruct(r, o, eltype);
-                       else
-                               r = Natives.writeValue(r, marshalBasic(o, 
eltype), itype);
-               }
-               
-               return new Ptr(ret);
-       }
-
-       private void unmarshalArray(long ptr, Object arr, Class eltype) {
-               if (ptr == 0)
-                       throw new CInvokeError("Reading array from null 
pointer");
-               int numels = Array.getLength(arr);
-               
-               int itype = gettypeint(eltype, false);
-               int elsize = sizeof(eltype);
-
-               long p = ptr;
-               for (int i = 0; i < numels; i++) {
-                       Object toset;
-                       if (itype == STRUCT_TYPE)
-                               toset = unmarshalStruct(p, eltype);
-                       else
-                               toset = Natives.readValue(p, eltype, itype);
-                       Array.set(arr, i, toset);
-
-                       p += elsize;
-               }
-       }
-
-       private NativeStruct getNativeStruct(Class cls) {
-               NativeStruct ret = (NativeStruct)_structs.get(cls);
-
-               if (ret == null) {
-                       long st = Natives.createStruct(_ctx);
-                       if (st == 0)
-                               fail();
-                       Field[] fields = cls.getFields();
-                       for (int i = 0; i < fields.length; i++) {
-                               Class tcls = fields[i].getType();
-                               if (tcls.isArray()) {
-                                       Natives.deleteStruct(_ctx, st);
-                                       throw new CInvokeError(
-                                               "Array structure members not 
supported");
-                               }
-                               if (tcls.isInterface()) {
-                                       Natives.deleteStruct(_ctx, st);
-                                       throw new CInvokeError(
-                                               "Callback structure members not 
supported");
-                               }
-                               if (tcls.equals(String.class)) {
-                                       Natives.deleteStruct(_ctx, st);
-                                       throw new CInvokeError(
-                                               "String structure members not 
supported");
-                               }
-                               int type = gettypeint(tcls, false);
-                               if (type == STRUCT_TYPE) {
-                                       if (Natives.addStructMemberStruct(_ctx, 
st,
-                                               fields[i].getName(),
-                                               getNativeStruct(tcls).st) == 0) 
{
-                                               try { fail(); }
-                                               finally { 
Natives.deleteStruct(_ctx, st); }
-                                       }
-                               } else {
-                                       if (Natives.addValueMemberStruct(_ctx, 
st,
-                                               fields[i].getName(), type) == 
0) {
-                                               try { fail(); }
-                                               finally { 
Natives.deleteStruct(_ctx, st); }
-                                       }
-                               }
-                       }
-                       if (Natives.finishStruct(_ctx, st) == 0) {
-                               try { fail(); } finally { 
Natives.deleteStruct(_ctx, st); }
-                       }
-                       ret = new NativeStruct(_ctx, st);
-                       _structs.put(cls, ret);
-               }
-               
-               return ret;
-       }
-
-       public String ptrToString(Ptr ptr, int numchars) {
-               if (_encoding == CInvoke.ENC.UNICODE)
-                       return Natives.ptrToStringUnicode(ptr.longValue(), 
numchars);
-               else
-                       return Natives.ptrToStringUTF8(ptr.longValue());
-       }
-       public Object[] ptrToArray(Ptr ptr, Class eltype, int num) {
-               if (eltype.isInterface())
-                       throw new CInvokeError("Arrays of callbacks not 
supported");
-
-               Object ret = Array.newInstance(eltype, num);
-
-               unmarshalArray(ptr.longValue(), ret, eltype);
-
-               return (Object[])ret;
-       }
-       public int sizeof(Class type) {
-               int itype = gettypeint(type, false);
-               if (itype == STRUCT_TYPE) {
-                       int ret = Natives.sizeStruct(_ctx, 
getNativeStruct(type).st);
-                       if (ret == -1)
-                               fail();
-                       return ret;
-               } else
-                       return Natives.sizeofBasic(itype);
-       }
-       public int sizeof(Object obj) {
-               Class cls = obj.getClass();
-               if (cls.isArray()) {
-                       if (cls.isInterface())
-                               throw new CInvokeError("Arrays of callbacks not 
supported");
-                       return Array.getLength(obj) * 
sizeof(cls.getComponentType());
-               } else
-                       return sizeof(cls);
-       }
 }

Modified: trunk/cinvoke/bindings/java/org/cinvoke/CInvoke.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/CInvoke.java        2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/CInvoke.java        2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,27 +1,217 @@
 package org.cinvoke;
 import java.lang.reflect.*;
 
+/**
+ * Provides interfaces and related utility methods for calling C libraries.
+ * The CInvoke class is the main public class in the C/Invoke Java binding.
+ * In addition to the load() methods, which connect Java interfaces to native
+ * shared libraries, it contains methods which can marshal parameters or
+ * return values in situations where the library cannot determine the correct
+ * marshaling behavior on its own.
+ */
 public final class CInvoke {
+       /**
+        * An enumeration of values representing different calling conventions.
+        */
        public class CC {
+               /**
+                * The default calling convention on the current platform.
+                */
                public static final int DEFAULT = -1;
+               /**
+                * The cdecl calling convention is the most common convention 
on x86.
+                */
                public static final int CDECL = 0;
+               /**
+                 * The stdcall convention is used by the Microsoft Windows API.
+                 */
                public static final int STDCALL = 1;
+               /**
+                * The fastcall convention is rarely used under Microsoft 
Windows.
+                */
                public static final int FASTCALL = 2;
        }
+       /**
+        * An enumeration which determines the encoding to use when marshalling
+        * strings.
+        */
        public class ENC {
+               /**
+                * Marshal strings using the Java UTF-8 variant.
+                */
                public static final int UTF8 = 0;
+               /**
+                * Marshal strings as two-byte Unicode values.
+                */
                public static final int UNICODE = 1;
        }
 
+       private static Natives _n;
+
+       static {
+               _n = new Natives();
+       }
+
+       /** 
+        * Loads a native C library and attaches it to the given Java interface.
+        * See the documentation for the address@hidden #load(String, Class, 
int, int)}
+        * overload for more information.  Using this overload calls functions
+        * with the default calling convention and the UTF-8 string encoding.
+        * @param libname The platform-specific name of the library to load.
+        * @param iface The interface to attach to the library.
+        * @return An object instance which implements the given interface.  
This
+        * object acts a proxy to the native C library.
+        */
        public static Object load(String libname, Class iface) {
                return load(libname, iface, CC.DEFAULT);
        }
+       /** 
+        * Loads a native C library and attaches it to the given Java interface.
+        * See the documentation for the address@hidden #load(String, Class, 
int, int)}
+        * overload for more information.  Using this overload calls functions
+        * with the UTF-8 string encoding.
+        * @param libname The platform-specific name of the library to load.
+        * @param iface The interface to attach to the library.
+        * @param callconv The calling convention to use on functions in this
+        * library, from the address@hidden CInvoke.CC} enumeration.
+        * @return An object instance which implements the given interface.  
This
+        * object acts a proxy to the native C library.
+        */
        public static Object load(String libname, Class iface, int callconv) {
                return load(libname, iface, CC.DEFAULT, ENC.UTF8);
        }
+       /** 
+        * Loads a native C library and attaches it to the given Java interface.
+        * Each method in the given interface should correspond to a function
+        * symbol in the given library. However, individual symbols are not
+        * resolved until their corresponding methods are called for the first 
time.
+        * The signature of the interface method determines how
+        * parameters and return values are marshaled to and from C.  The 
following
+        * types are allowed in method signatures:
+        * <li> <i>byte, Byte</i>: Marshaled as a C 'char' type.
+        * <li> <i>short, Short</i>: Marshaled as a 2-byte integer.
+        * <li> <i>int, Integer</i>: Marshaled as a 4-byte integer.
+        * <li> <i>long, Long</i>: Marshaled as an 8-byte integer.
+        * <li> <i>float, Float</i>: Marshaled as a C 'float' type.
+        * <li> <i>double, Double</i>: Marshaled as a C 'double' type.
+        * <li> <i>address@hidden NativeShort}</i>: Marshaled as a C 'short' 
type.
+        * <li> <i>address@hidden NativeInt}</i>: Marshaled as a C 'int' type.
+        * <li> <i>address@hidden NativeLong}</i>: Marshaled as a C 'long' type.
+        * <li> <i>address@hidden NativeLongLong}</i>: Marshaled as a C 'long 
long' type.
+        * <li> <i>address@hidden Ptr}</i>: Marshaled a C pointer value (i.e. a 
void*, or
+        * any other pointer of the same size).
+        * <li> <i>String</i>: Marshaled as a constant string pointer, with 
either
+        * UTF-8 or Unicode encoding.  When used as a return value, marshaling
+        * continues up until the first 0 character.
+        * <li> <i>Any Interface</i>: If an interface type is specified for a
+        * parameter, then an instance of the interface will be marshaled as a
+        * function pointer.  The first method defined in the interface will be
+        * called back when unmanaged code calls the function pointer.  
Therefore,
+        * the prototype of this method should match the callback protoype.
+        * Callbacks are currently only supported when all the calls to a
+        * callback are made from within the calling function.  Passing a 
managed
+        * function pointer to a C function which stores the value and calls it
+        * later in another thread may result in undefined behavior.  Interfaces
+        * cannot be used as return types.
+        * <li> <i>Any Array Type</i>: Arrays of any other valid type are 
marshaled
+        * as pointers to C array values.  Arrays, unlike Strings, are mutable;
+        * their elements are writable by unmanaged code, and after a C function
+        * returns, any value written to an array element is marshaled back to
+        * a corresponding Java value.  This means you can use arrays whenever
+        * pointer or pass-by-reference semantics are required.  However, 
arrays of
+        * interfaces or Strings are not supported, and using an array as a 
return
+        * type is not supported (use address@hidden ptrToString(Ptr, int, int) 
ptrToString}
+        * or address@hidden ptrToArray(Ptr, Class, int) ptrToArray} instead).
+        * <li> <i>Any Class</i>: Class types other than those listed above are
+        * marshaled as C structures, with each public field of a class
+        * corresponding to a structure member.  Structures cannot contain 
members
+        * that are arrays, Strings, or interfaces.  Members which have class 
types
+        * are treated as embedded structure values.  Structures can never be
+        * passed or returned by value, only inside arrays.  To pass a pointer 
to
+        * a structure to a function, pass an array with a length of 1.  To 
return
+        * a pointer to a function, return a Ptr value and convert it to an 
array
+        * of structures with address@hidden ptrToArray(Ptr, Class, int) 
ptrToArray}.
+        * @param libname The platform-specific name of the library to load.
+        * This is usually the name of a file containing the shared object file,
+        * i.e. mylib.dll or /lib/libmylib.so.  The search path for library 
files
+        * is also implementation and system-defined; specifying the full path 
to
+        * a library file usually yields the most portable behavior.
+        * @param iface The interface to attach to the library.  The returned
+        * object implements this interface.
+        * @param callconv The calling convention to use on functions in this
+        * library, from the address@hidden CInvoke.CC} enumeration.
+        * @param encoding The encoding to use when marshaling strings in and 
out
+        * of this library, from the address@hidden CInvoke.ENC} enumeration.
+        * @return An object instance which implements the given interface.  
This
+        * object acts a proxy to the native C library.  When a method in the 
given
+        * interface is called on this object, the name of the method is used as
+        * a symbol name to be looked up in the library.  The parameters to the
+        * method are translated to their C equivalents, the C function is 
called,
+        * and the return value (and any array values) are translated back to
+        * Java objects.
+        */
        public static Object load(String libname, Class iface, int callconv,
                int encoding) {
                return Proxy.newProxyInstance(iface.getClassLoader(),
                        new Class[] { iface }, new CInvProxy(libname, callconv, 
encoding));
        }
+
+       /** 
+        * Converts a pointer to an unmanaged buffer to a Java string value.
+        * @param ptr A pointer value which points to an array of bytes or
+        * Unicode characters.
+        * @param numchars The number of characters in the string.  Specify a
+        * negative value
+        * to stop conversion at the first 0 character.  This parameter is 
ignored
+        * when using the UTF-8 encoding, which always stops at the first 0 
byte.
+        * @param encoding The encoding to use, must be one of the values from 
the
+        * address@hidden CInvoke.ENC} enumeration.
+        * @return The completed String value.
+        */
+       public static String ptrToString(Ptr ptr, int numchars, int encoding) {
+               synchronized (_n) {
+                       return _n.ptrToString(ptr, numchars, encoding);
+               }
+       }
+       /** 
+        * Converts a pointer to a native array to a Java array value.
+        * @param ptr A pointer value which points to a contiguous array of
+        * unmanaged values.
+        * @param eltype The type of the elements of the array to create.  Must
+        * be either a class with public fields (marshalled as a C structure) or
+        * a "basic" type (Byte, Short, Int, Long, Float, Double, NativeShort,
+        * NativeInt, NativeLong, NativeLongLong, or Ptr).
+        * @param num The number of elements in the array.
+        * @return The completed Java array, cast to the Object[] type.
+        */
+       public static Object[] ptrToArray(Ptr ptr, Class eltype, int num) {
+               synchronized (_n) {
+                       return _n.ptrToArray(ptr, eltype, num);
+               }
+       }
+       /** 
+        * Utility method which returns the number of bytes required to hold an
+        * instance of the given marshalable type.
+        * @param type The type to retrieve the size of.
+        * @return The number of bytes of unmanaged memory required to hold an
+        * instance of the specified type.
+        */
+       public static int getSize(Class type) {
+               synchronized (_n) {
+                       return _n.getSize(type);
+               }
+       }
+       /** 
+        * Utility method which returns the number of bytes required
+        * to hold the given marshalable value.  If the value is an array,
+        * the size returned will be the combined size of all array elements.
+        * @param obj The object to retrieve the size of.
+        * @return The number of bytes of unmanaged memory required to hold the
+        * object.
+        */
+       public static int getSize(Object obj) {
+               synchronized (_n) {
+                       return _n.getSize(obj);
+               }
+       }
 }

Modified: trunk/cinvoke/bindings/java/org/cinvoke/CInvokeError.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/CInvokeError.java   2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/CInvokeError.java   2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,6 +1,13 @@
 package org.cinvoke;
 
+/**
+ * Thrown when an error occurs in the C/Invoke Java binding.
+ */
 public class CInvokeError extends Error {
+       /**
+        * Initializes a CInvokeError object.
+        * @param msg An error message.
+        */
        public CInvokeError(String msg) {
                super(msg);
        }

Modified: trunk/cinvoke/bindings/java/org/cinvoke/NativeInt.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/NativeInt.java      2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/NativeInt.java      2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,13 +1,42 @@
 package org.cinvoke;
+import java.io.Serializable;
 
-public final class NativeInt {
+/**
+ * Used to send or read values of the C type 'int'.  The size of integer values
+ * in C can vary with the current native platform.  Declaring native interfaces
+ * with this type will always marshal the corresponding values as the correct
+ * size.
+ */
+public final class NativeInt implements Serializable {
+       /**
+        * Initializes a NativeInt instance.
+        * @param val The value to marshal.  Note that not all the bits in the 
long
+        * value are guaranteed to be used by the called platform.
+        */
        public NativeInt(long val) {
                _val = val;
        }
+       /**
+        * Returns a marshaled value.
+        * @return The marshaled value.  Note that not all the bits in the long
+        * value are guaranteed to be used by the called platform.
+        */
        public long longVal() {
                return _val;
        }
 
+       public boolean equals(Object o) {
+               if (o == null) return false;
+               if (this == o) return true;
+               if (!(NativeInt.class.isInstance(o))) return false;
+               NativeInt ni = (NativeInt)o;
+               return _val == ni._val;
+       }
+       public int hashCode() {
+               return new Long(_val).hashCode();
+       }
        private long _val;
+
+       private static final long serialVersionUID = 1;
 }
-       
+

Modified: trunk/cinvoke/bindings/java/org/cinvoke/NativeLong.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/NativeLong.java     2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/NativeLong.java     2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,13 +1,42 @@
 package org.cinvoke;
+import java.io.Serializable;
 
-public final class NativeLong {
+/**
+ * Used to send or read values of the C type 'long'.  The size of integer 
values
+ * in C can vary with the current native platform.  Declaring native interfaces
+ * with this type will always marshal the corresponding values as the correct
+ * size.
+ */
+public final class NativeLong implements Serializable {
+       /**
+        * Initializes a NativeLong instance.
+        * @param val The value to marshal.  Note that not all the bits in the 
long
+        * value are guaranteed to be used by the called platform.
+        */
        public NativeLong(long val) {
                _val = val;
        }
+       /**
+        * Returns a marshaled value.
+        * @return The marshaled value.  Note that not all the bits in the long
+        * value are guaranteed to be used by the called platform.
+        */
        public long toLong() {
                return _val;
        }
 
+       public boolean equals(Object o) {
+               if (o == null) return false;
+               if (this == o) return true;
+               if (!(NativeLong.class.isInstance(o))) return false;
+               NativeLong ni = (NativeLong)o;
+               return _val == ni._val;
+       }
+       public int hashCode() {
+               return new Long(_val).hashCode();
+       }
        private long _val;
+
+       private static final long serialVersionUID = 1;
 }
-       
+

Modified: trunk/cinvoke/bindings/java/org/cinvoke/NativeLongLong.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/NativeLongLong.java 2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/NativeLongLong.java 2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,13 +1,43 @@
 package org.cinvoke;
+import java.io.Serializable;
 
-public final class NativeLongLong {
+/**
+ * Used to send or read values of the C type 'long long', if it is available.
+ * The size of integer values
+ * in C can vary with the current native platform.  Declaring native interfaces
+ * with this type will always marshal the corresponding values as the correct
+ * size.
+ */
+public final class NativeLongLong implements Serializable {
+       /**
+        * Initializes a NativeLongLong instance.
+        * @param val The value to marshal.  Note that not all the bits in the 
long
+        * value are guaranteed to be used by the called platform.
+        */
        public NativeLongLong(long val) {
                _val = val;
        }
+       /**
+        * Returns a marshaled value.
+        * @return The marshaled value.  Note that not all the bits in the long
+        * value are guaranteed to be used by the called platform.
+        */
        public long longValue() {
                return _val;
        }
 
+       public boolean equals(Object o) {
+               if (o == null) return false;
+               if (this == o) return true;
+               if (!(NativeLongLong.class.isInstance(o))) return false;
+               NativeLongLong ni = (NativeLongLong)o;
+               return _val == ni._val;
+       }
+       public int hashCode() {
+               return new Long(_val).hashCode();
+       }
        private long _val;
+
+       private static final long serialVersionUID = 1;
 }
        

Modified: trunk/cinvoke/bindings/java/org/cinvoke/NativeShort.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/NativeShort.java    2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/NativeShort.java    2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,13 +1,43 @@
 package org.cinvoke;
+import java.io.Serializable;
 
-public final class NativeShort {
+/**
+ * Used to send or read values of the C type 'short'. 
+ * The size of integer values
+ * in C can vary with the current native platform.  Declaring native interfaces
+ * with this type will always marshal the corresponding values as the correct
+ * size.
+ */
+public final class NativeShort implements Serializable {
+       /**
+        * Initializes a NativeShort instance.
+        * @param val The value to marshal.  Note that not all the bits in the 
int
+        * value are guaranteed to be used by the called platform.
+        */
        public NativeShort(int val) {
                _val = val;
        }
+       /**
+        * Returns a marshaled value.
+        * @return The marshaled value.  Note that not all the bits in the int
+        * value are guaranteed to be used by the called platform.
+        */
        public int intValue() {
                return _val;
        }
 
+       public boolean equals(Object o) {
+               if (o == null) return false;
+               if (this == o) return true;
+               if (!(NativeShort.class.isInstance(o))) return false;
+               NativeShort ni = (NativeShort)o;
+               return _val == ni._val;
+       }
+       public int hashCode() {
+               return new Integer(_val).hashCode();
+       }
        private int _val;
+
+       private static final long serialVersionUID = 1;
 }
        

Modified: trunk/cinvoke/bindings/java/org/cinvoke/Natives.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/Natives.java        2006-07-06 
22:21:17 UTC (rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/Natives.java        2006-07-07 
04:38:40 UTC (rev 76)
@@ -1,4 +1,6 @@
 package org.cinvoke;
+import java.util.*;
+import java.lang.reflect.*;
 
 class Natives {
        static {
@@ -46,15 +48,438 @@
        public static native long stringToPtrUTF8(String str);
        public static native long stringToPtrUnicode(String str);
 
-       public static final int T_JSHORT = -1;
-       public static final int T_JINT = -2;
-       public static final int T_JLONG = -3;
-       public static final int T_CHAR = 0;
-       public static final int T_SHORT = 1;
-       public static final int T_INT = 2;
-       public static final int T_LONG = 3;
-       public static final int T_EXTRALONG = 4;
-       public static final int T_FLOAT = 5;
-       public static final int T_DOUBLE = 6;
-       public static final int T_PTR = 7;
+       private static final int T_JSHORT = -1;
+       private static final int T_JINT = -2;
+       private static final int T_JLONG = -3;
+       private static final int T_CHAR = 0;
+       private static final int T_SHORT = 1;
+       private static final int T_INT = 2;
+       private static final int T_LONG = 3;
+       private static final int T_EXTRALONG = 4;
+       private static final int T_FLOAT = 5;
+       private static final int T_DOUBLE = 6;
+       private static final int T_PTR = 7;
+
+       private final static int STRUCT_TYPE = -999;
+
+       public long _ctx = 0;
+       private HashMap _functions;
+       private HashMap _structs;
+
+       public Natives() {
+               _ctx = createContext();
+               if (_ctx == 0) throw new OutOfMemoryError();
+
+               _functions = new HashMap();
+               _structs = new HashMap();
+       }
+
+       public void close() {
+               for (Iterator i = _functions.values().iterator(); i.hasNext();)
+                       ((NativeMethod)i.next()).close();
+               for (Iterator i = _structs.values().iterator(); i.hasNext();) 
+                       ((NativeStruct)i.next()).close();
+               if (_ctx != 0) {
+                       deleteContext(_ctx);
+                       _ctx = 0;
+               }
+       }
+
+       public void fail() {
+               throw new CInvokeError(getError(_ctx));
+       }
+
+       class NativeStruct {
+               public NativeStruct(long ctx, long st) {
+                       _ctx = ctx;
+                       this.st = st;
+               }
+
+               public void close() {
+                       if (st != 0) {
+                               deleteStruct(_ctx, st);
+                               st = 0;
+                       }
+               }
+
+               public long st;
+               private long _ctx;
+       }
+
+       class NativeMethod {
+               public NativeMethod(long ctx, long func, long ep, int[] types,
+                       boolean hasret, int rettype) {
+                       this.func = func;
+                       this.ep = ep;
+                       this.types = types;
+                       this.hasret = hasret;
+                       this.rettype = rettype;
+                       _ctx = ctx;
+               }
+
+               public void close() {
+                       if (func != 0) {
+                               deleteFunction(_ctx, func);
+                               func = 0;
+                       }
+               }
+
+               private long _ctx;
+               public long func;
+               public long ep;
+               public int[] types;
+               public boolean hasret;
+               public int rettype;
+       }
+
+       public NativeMethod createNativeMethod(Method method, long lib, int cc) 
{
+               NativeMethod meth = (NativeMethod)_functions.get(method);
+               if (meth == null) {
+                       meth = createNative(method, lib, cc);
+                       _functions.put(method, meth);
+               }
+               return meth;
+       }
+       
+       private int gettypeint(Class cls, boolean thrw) {
+               if (cls.isArray()) {
+                       if (cls.isInterface())
+                               throw new CInvokeError("Arrays of callbacks not 
supported");
+                       if (cls.equals(String.class))
+                               throw new CInvokeError("Arrays of strings not 
supported");
+                       return T_PTR;
+               } else {
+                       if (cls.isInterface())
+                               return T_PTR;
+                       else if (cls.equals(String.class))
+                               return T_PTR;
+                       else if (cls.equals(Byte.class))
+                               return T_CHAR;
+                       else if (cls.equals(Short.class))
+                               return T_JSHORT;
+                       else if (cls.equals(Integer.class))
+                               return T_JINT;
+                       else if (cls.equals(Long.class))
+                               return T_JLONG;
+                       else if (cls.equals(Float.class))
+                               return T_FLOAT;
+                       else if (cls.equals(Double.class))
+                               return T_DOUBLE;
+                       else if (cls.equals(NativeShort.class))
+                               return T_SHORT;
+                       else if (cls.equals(NativeInt.class))
+                               return T_INT;
+                       else if (cls.equals(NativeLong.class))
+                               return T_LONG;
+                       else if (cls.equals(NativeLongLong.class))
+                               return T_EXTRALONG;
+                       else if (cls.equals(Ptr.class))
+                               return T_PTR;
+                       else {
+                               if (thrw)
+                                       throw new CInvokeError(
+                                       "Passing or returning structures by 
value not supported");
+                               else
+                                       return STRUCT_TYPE;
+                       }
+               }
+       }
+
+       private char gettypechar(int type) {
+               switch (type) {
+               case T_JSHORT:
+                       return '2';
+               case T_JINT:
+                       return '4';
+               case T_JLONG:
+                       return '8';
+               case T_CHAR:
+                       return 'c';
+               case T_SHORT:
+                       return 's';
+               case T_INT:
+                       return 'i';
+               case T_LONG:
+                       return 'l';
+               case T_EXTRALONG:
+                       return 'e';
+               case T_FLOAT:
+                       return 'f';
+               case T_DOUBLE:
+                       return 'd';
+               case T_PTR:
+                       return 'p';
+               default:
+                       throw new UnknownError("unknown type");
+               }
+       }
+
+       private NativeMethod createNative(Method method, long lib, int cc) {
+               long ep = loadEPLibrary(_ctx, lib, method.getName());
+               if (ep == 0)
+                       fail();
+               StringBuffer retfmt = new StringBuffer();
+               StringBuffer parmfmt = new StringBuffer();
+               boolean hasret = false;
+               int rettype = 0;
+               Class retcls = method.getReturnType();
+               if (!retcls.equals(Void.TYPE)) {
+                       if (retcls.isArray())
+                               throw new CInvokeError("returning arrays not 
supported");
+                       if (retcls.isInterface())
+                               throw new CInvokeError("returning callbacks not 
supported");
+                       hasret = true;
+                       rettype = gettypeint(retcls, true);
+                       retfmt.append(gettypechar(rettype));
+               }
+
+               Class[] pclasses = method.getParameterTypes();
+               int[] types = new int[pclasses.length];
+               for (int i = 0; i < types.length; i++) {
+                       types[i] = gettypeint(pclasses[i], true);
+                       parmfmt.append(gettypechar(types[i]));
+               }
+
+               long func = createFunction(_ctx, cc, retfmt.toString(),
+                       parmfmt.toString());
+               if (func == 0)
+                       fail();
+               return new NativeMethod(_ctx, func, ep, types, hasret, rettype);
+       }
+
+       public Object unmarshalString(long p, int encoding) {
+               if (p == 0) return null;
+               if (encoding == CInvoke.ENC.UNICODE)
+                       return ptrToStringUnicode(p, -1);
+               else
+                       return ptrToStringUTF8(p);
+       }
+
+       private Object unmarshalStruct(long ptr, Class cls) {
+               long st = getNativeStruct(cls).st;
+               Field[] fields = cls.getFields();
+               Object ret;
+
+               try {
+                       ret = cls.newInstance();
+               } catch (IllegalAccessException iae) {
+                       throw new CInvokeError("Cannot create new instance of 
class " +
+                               cls.getName() + " due a security error: " + 
iae.toString());
+               } catch (InstantiationException ie) {
+                       throw new CInvokeError("Cannot create new instance of 
class " +
+                               cls.getName() + " due to error: " + 
ie.toString());
+               }
+               for (int i = 0; i < fields.length; i++) {
+                       Field fld = fields[i];
+                       Class tcls = fld.getType();
+                       Object val;
+                       int type = gettypeint(tcls, false);
+                       if (type == STRUCT_TYPE) {
+                               long p = getMemberPtrStruct(_ctx, st, ptr,
+                                       fld.getName());
+                               if (p == 0) fail();
+                               val = unmarshalStruct(p, tcls);
+                       } else {
+                               val = getMemberValueStruct(_ctx, st, ptr,
+                                       fld.getName(), tcls, type);
+                       }
+                       try {
+                               fld.set(ret, val);
+                       } catch (IllegalAccessException iae) {
+                               throw new CInvokeError(cls.getName() +
+                                       " field access failed: " + 
iae.toString());
+                       }
+               }
+               
+               return ret;
+       }
+
+       private long marshalStruct(long outp, Object s, Class cls) {
+               if (s == null)
+                       throw new CInvokeError("Invalid null value");
+
+               long st = getNativeStruct(cls).st;
+               Field[] fields = cls.getFields();
+               for (int i = 0; i < fields.length; i++) {
+                       Field fld = fields[i];
+                       Class tcls = fld.getType();
+                       Object val;
+                       try {
+                               val = fld.get(s);
+                       } catch (IllegalAccessException iae) {
+                               throw new CInvokeError(cls.getName() +
+                                       " field access failed: " + 
iae.toString());
+                       }
+                       int type = gettypeint(tcls, false);
+                       if (type == STRUCT_TYPE) {
+                               long p = getMemberPtrStruct(_ctx, st,
+                                       outp, fld.getName());
+                               if (p == 0) fail();
+                               marshalStruct(p, val, tcls);
+                       } else {
+                               if (setMemberValueStruct(_ctx, st, outp,
+                                       fld.getName(), val, type) == 0)
+                                       fail();
+                       }
+               }
+
+               int sz = sizeStruct(_ctx, st);
+               if (sz == -1) fail();
+               return outp + sz;
+       }
+
+       public Object marshalBasic(Object o, Class cls) {
+               if (o == null) {
+                       if (cls.equals(Ptr.class))
+                               return new Ptr(0);
+                       else
+                               throw new CInvokeError("Invalid null value");
+               } else
+                       return o;
+       }
+
+       public Ptr marshalString(String str, int encoding) {
+               if (str == null) return new Ptr(0);
+
+               long l;
+               if (encoding == CInvoke.ENC.UNICODE)
+                       l = stringToPtrUnicode(str);
+               else 
+                       l = stringToPtrUTF8(str);
+               if (l == 0)
+                       throw new OutOfMemoryError();
+               return new Ptr(l);
+       }
+
+       public Ptr marshalArray(Class eltype, Object val) {
+               if (val == null) return new Ptr(0);
+
+               int numels = Array.getLength(val);
+               int len = numels * getSize(eltype);
+               
+               long ret = alloc(len);
+               if (ret == 0)
+                       throw new OutOfMemoryError();
+               
+               int itype = gettypeint(eltype, false);
+
+               long r = ret;
+               for (int i = 0; i < numels; i++) {
+                       Object o = Array.get(val, i);
+                       if (itype == -909)
+                               r = marshalStruct(r, o, eltype);
+                       else
+                               r = writeValue(r, marshalBasic(o, eltype), 
itype);
+               }
+               
+               return new Ptr(ret);
+       }
+
+       public void unmarshalArray(long ptr, Object arr, Class eltype) {
+               if (ptr == 0)
+                       throw new CInvokeError("Reading array from null 
pointer");
+               int numels = Array.getLength(arr);
+               
+               int itype = gettypeint(eltype, false);
+               int elsize = getSize(eltype);
+
+               long p = ptr;
+               for (int i = 0; i < numels; i++) {
+                       Object toset;
+                       if (itype == STRUCT_TYPE)
+                               toset = unmarshalStruct(p, eltype);
+                       else
+                               toset = readValue(p, eltype, itype);
+                       Array.set(arr, i, toset);
+
+                       p += elsize;
+               }
+       }
+
+       private NativeStruct getNativeStruct(Class cls) {
+               NativeStruct ret = (NativeStruct)_structs.get(cls);
+
+               if (ret == null) {
+                       long st = createStruct(_ctx);
+                       if (st == 0)
+                               fail();
+                       Field[] fields = cls.getFields();
+                       for (int i = 0; i < fields.length; i++) {
+                               Class tcls = fields[i].getType();
+                               if (tcls.isArray()) {
+                                       deleteStruct(_ctx, st);
+                                       throw new CInvokeError(
+                                               "Array structure members not 
supported");
+                               }
+                               if (tcls.isInterface()) {
+                                       deleteStruct(_ctx, st);
+                                       throw new CInvokeError(
+                                               "Callback structure members not 
supported");
+                               }
+                               if (tcls.equals(String.class)) {
+                                       deleteStruct(_ctx, st);
+                                       throw new CInvokeError(
+                                               "String structure members not 
supported");
+                               }
+                               int type = gettypeint(tcls, false);
+                               if (type == STRUCT_TYPE) {
+                                       if (addStructMemberStruct(_ctx, st,
+                                               fields[i].getName(),
+                                               getNativeStruct(tcls).st) == 0) 
{
+                                               try { fail(); }
+                                               finally { deleteStruct(_ctx, 
st); }
+                                       }
+                               } else {
+                                       if (addValueMemberStruct(_ctx, st,
+                                               fields[i].getName(), type) == 
0) {
+                                               try { fail(); }
+                                               finally { deleteStruct(_ctx, 
st); }
+                                       }
+                               }
+                       }
+                       if (finishStruct(_ctx, st) == 0) {
+                               try { fail(); } finally { deleteStruct(_ctx, 
st); }
+                       }
+                       ret = new NativeStruct(_ctx, st);
+                       _structs.put(cls, ret);
+               }
+               
+               return ret;
+       }
+
+       public String ptrToString(Ptr ptr, int numchars, int encoding) {
+               if (encoding == CInvoke.ENC.UNICODE)
+                       return ptrToStringUnicode(ptr.longValue(), numchars);
+               else
+                       return ptrToStringUTF8(ptr.longValue());
+       }
+       public Object[] ptrToArray(Ptr ptr, Class eltype, int num) {
+               if (eltype.isInterface())
+                       throw new CInvokeError("Arrays of callbacks not 
supported");
+
+               Object ret = Array.newInstance(eltype, num);
+
+               unmarshalArray(ptr.longValue(), ret, eltype);
+
+               return (Object[])ret;
+       }
+       public int getSize(Class type) {
+               int itype = gettypeint(type, false);
+               if (itype == STRUCT_TYPE) {
+                       int ret = sizeStruct(_ctx, getNativeStruct(type).st);
+                       if (ret == -1)
+                               fail();
+                       return ret;
+               } else
+                       return sizeofBasic(itype);
+       }
+       public int getSize(Object obj) {
+               Class cls = obj.getClass();
+               if (cls.isArray()) {
+                       if (cls.isInterface())
+                               throw new CInvokeError("Arrays of callbacks not 
supported");
+                       return Array.getLength(obj) * 
getSize(cls.getComponentType());
+               } else
+                       return getSize(cls);
+       }
 }

Modified: trunk/cinvoke/bindings/java/org/cinvoke/Ptr.java
===================================================================
--- trunk/cinvoke/bindings/java/org/cinvoke/Ptr.java    2006-07-06 22:21:17 UTC 
(rev 75)
+++ trunk/cinvoke/bindings/java/org/cinvoke/Ptr.java    2006-07-07 04:38:40 UTC 
(rev 76)
@@ -1,13 +1,51 @@
 package org.cinvoke;
+import java.io.Serializable;
 
-public final class Ptr {
+/** Used to send or read values the size of a C pointer type.  The size of
+ * pointer values in C can vary with the current native platform.  Declaring
+ * native interfaces with this type will always marshal the corresponding
+ * values as the correct size.
+ */
+public final class Ptr implements Serializable {
+       /**
+        * Initializes a Ptr instance.
+        * @param val The value to marshal.  Note that not all the bits in the 
long
+        * value are guaranteed to be used by the called platform.  Directly 
using
+        * this constructor is discouraged.  In particular, the C standard does
+        * not guarantee an integer representation for pointer values, so using
+        * this constructor may be undefined.  The only integer value which is
+        * always defined is 0, which is equivalent to the NULL pointer.  
Otherwise,
+        * you should only pass Ptr values to C functions which you have 
received
+        * as return values from other C functions. */
        public Ptr(long val) {
                _val = val;
        }
+       /**
+       * Returns a marshaled value.
+       * @return The marshaled value.  Note that not all the bits in the long
+       * value are guaranteed to be used by the called platform.  Use of this
+       * method is discouraged.  In particular, the C standard does
+       * not guarantee an integer representation for pointer values, so using
+       * this method may be undefined.  The only integer value which is
+       * always defined is 0, which is equivalent to the NULL pointer.  
Otherwise,
+       * you should only pass Ptr values to C functions which you have received
+       * as return values from other C functions. */
        public long longValue() {
                return _val;
        }
 
+       public boolean equals(Object o) {
+               if (o == null) return false;
+               if (this == o) return true;
+               if (!(Ptr.class.isInstance(o))) return false;
+               Ptr ni = (Ptr)o;
+               return _val == ni._val;
+       }
+       public int hashCode() {
+               return new Long(_val).hashCode();
+       }
        private long _val;
+
+       private static final long serialVersionUID = 1;
 }
        





reply via email to

[Prev in Thread] Current Thread [Next in Thread]