From: <wme...@us...> - 2009-09-04 00:44:12
|
Revision: 6746 http://jython.svn.sourceforge.net/jython/?rev=6746&view=rev Author: wmeissner Date: 2009-09-04 00:43:55 +0000 (Fri, 04 Sep 2009) Log Message: ----------- Implement c_char_p properly, and string return values Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Util.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/AbstractMemoryCData.java branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/CoreExposed.includes 2009-09-04 00:43:55 UTC (rev 6746) @@ -63,6 +63,7 @@ org/python/modules/jffi/PointerCData.class org/python/modules/jffi/Structure.class org/python/modules/jffi/ScalarCData.class +org/python/modules/jffi/StringCData.class org/python/modules/jffi/StructLayout.class org/python/modules/jffi/StructLayout$Field.class org/python/modules/jffi/StructLayout$ScalarField.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-04 00:43:55 UTC (rev 6746) @@ -208,7 +208,7 @@ c_size_t = c_ulong c_ssize_t = c_long -class c_char_p(_ScalarCData): +class c_char_p(jffi.StringCData): _type_ = 'z' _jffi_type = jffi.Type.STRING Added: branches/ctypes-jffi/src/org/python/modules/jffi/AbstractMemoryCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/AbstractMemoryCData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/AbstractMemoryCData.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -0,0 +1,29 @@ + +package org.python.modules.jffi; + +import org.python.core.PyType; + +public abstract class AbstractMemoryCData extends CData implements Pointer { + protected DirectMemory memory; + + AbstractMemoryCData(PyType subtype, CType type, DirectMemory memory) { + super(subtype, type); + this.memory = memory; + } + @Override + public boolean __nonzero__() { + return !getMemory().isNull(); + } + + protected void initReferenceMemory(Memory m) { + m.putAddress(0, memory); + } + + public final long getAddress() { + return getMemory().getAddress(); + } + + public final DirectMemory getMemory() { + return hasReferenceMemory() ? getReferenceMemory().getMemory(0) : memory; + } +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -100,7 +100,18 @@ final long ptr = IO.getAddress(address + offset); return ptr != 0 ? new NativeMemory(ptr) : null; } + + public final byte[] getZeroTerminatedByteArray(long offset) { + checkBounds(offset, 1); + return IO.getZeroTerminatedByteArray(address + offset, (int) (size - offset)); + } + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) { + // Ensure room for terminating zero byte + checkBounds(offset, len + 1); + IO.putZeroTerminatedByteArray(address + offset, bytes, off, len); + } + public final void putByte(long offset, byte value) { checkBounds(offset, 1); IO.putByte(address + offset, value); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -74,6 +74,9 @@ case POINTER: return new PointerInvoker(function, marshallers); + case STRING: + return new StringInvoker(function, marshallers); + default: break; } @@ -325,6 +328,17 @@ return Py.newLong(jffiInvoker.invokeAddress(jffiFunction, convertArguments(args))); } } + + private static final class StringInvoker extends BaseInvoker { + private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); + public StringInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newString(jffiInvoker.invokeAddress(jffiFunction, convertArguments(args))); + } + } /*------------------------------------------------------------------------*/ static abstract class BaseMarshaller implements ParameterMarshaller { @@ -414,7 +428,9 @@ public static final ParameterMarshaller INSTANCE = new StringMarshaller(); public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { - if (parameter instanceof PyNone) { + if (parameter instanceof StringCData) { + buffer.putAddress(((StringCData) parameter).getMemory().getAddress()); + } else if (parameter instanceof PyNone) { buffer.putAddress(0); } else { byte[] bytes = parameter.toString().getBytes(); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -87,6 +87,9 @@ case FLOAT: return Platform.getPlatform().getCPU() == Platform.CPU.I386 || Platform.getPlatform().getCPU() == Platform.CPU.X86_64; + + case STRING: + return Platform.getPlatform().addressSize() == 32; } } return false; @@ -283,6 +286,12 @@ } break; + case STRING: + if (Platform.getPlatform().addressSize() == 32) { + return StringResultConverter.INSTANCE; + } + break; + default: break; } @@ -570,6 +579,16 @@ } /** + * Converts a native string address result into into a python string instance + */ + static final class StringResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new StringResultConverter(); + public final PyObject pyValue(int value) { + return Util.newString(value); + } + } + + /** * Base class for all integer parameter converters. */ static abstract class BaseParameterConverter implements IntParameterConverter { Modified: branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -121,6 +121,14 @@ return IO.getAddress(buffer, index(offset)); } + public final byte[] getZeroTerminatedByteArray(long offset) { + checkBounds(offset, 1); + int len = indexOf(offset, (byte) 0); + byte[] bytes = new byte[len != -1 ? len : length - (int) offset]; + System.arraycopy(buffer, index(offset), bytes, 0, bytes.length); + return bytes; + } + public final void putByte(long offset, byte value) { checkBounds(offset, 1); buffer[index(offset)] = value; @@ -163,6 +171,14 @@ checkBounds(offset, ADDRESS_SIZE); IO.putAddress(buffer, index(offset), value); } + + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) { + // Ensure room for terminating zero byte + checkBounds(offset, len + 1); + System.arraycopy(bytes, off, buffer, index(offset), len); + buffer[len] = (byte) 0; + } + public final void get(long offset, byte[] dst, int off, int len) { checkBounds(offset, len); System.arraycopy(buffer, index(offset), dst, off, len); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -113,6 +113,14 @@ * pointed to by the address. */ public DirectMemory getMemory(long offset); + + /** + * Reads a zero terminated byte array (e.g. an ascii or utf-8 string) + * + * @param offset The offset within the memory area of the start of the string. + * @return A byte array containing a copy of the data. + */ + public byte[] getZeroTerminatedByteArray(long offset); /** * Writes an 8 bit integer value to the memory area at the specified offset. @@ -185,8 +193,18 @@ * @param value The pointer value to write to the memory location. */ public void putAddress(long offset, long value); - + /** + * Writes a byte array to memory, and appends a zero terminator + * + * @param offset The offset within the memory area of the start of the string. + * @param bytes The byte array to write to the memory. + * @param off The offset with the byte array to start copying. + * @param maxlen The number of bytes of the byte array to write to the memory area. (not including zero byte) + */ + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len); + + /** * Reads an array of bytes from the memory area at the specified offset. * * @param offset The offset within the memory area to read the bytes. Modified: branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -83,6 +83,14 @@ return ptr != 0 ? new NativeMemory(ptr) : null; } + public final byte[] getZeroTerminatedByteArray(long offset) { + return IO.getZeroTerminatedByteArray(address + offset); + } + + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) { + IO.putZeroTerminatedByteArray(address + offset, bytes, off, len); + } + public final void putByte(long offset, byte value) { IO.putByte(address + offset, value); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -11,15 +11,13 @@ import org.python.expose.ExposedType; @ExposedType(name = "jffi.PointerCData", base = CData.class) -public class PointerCData extends CData implements Pointer { +public class PointerCData extends AbstractMemoryCData implements Pointer { public static final PyType TYPE = PyType.fromClass(PointerCData.class); - private final DirectMemory memory; final MemoryOp componentMemoryOp; PointerCData(PyType subtype, CType type, DirectMemory memory, MemoryOp componentMemoryOp) { - super(subtype, type); - this.memory = memory; + super(subtype, type, memory); this.componentMemoryOp = componentMemoryOp; } @@ -59,23 +57,4 @@ public void setContents(PyObject value) { componentMemoryOp.put(getMemory(), 0, value); } - - @Override - public boolean __nonzero__() { - return !getMemory().isNull(); - } - - - protected void initReferenceMemory(Memory m) { - m.putAddress(0, memory); - } - - public final long getAddress() { - return getMemory().getAddress(); - } - - public final DirectMemory getMemory() { - return hasReferenceMemory() ? getReferenceMemory().getMemory(0) : memory; - } - } Added: branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -0,0 +1,70 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyNewWrapper; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedSet; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.StringCData", base = CData.class) +public class StringCData extends AbstractMemoryCData { + public static final PyType TYPE = PyType.fromClass(StringCData.class); + + public StringCData(PyType pytype, CType ctype, DirectMemory m) { + super(pytype, ctype, m); + } + + @ExposedNew + public static PyObject StringCData_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + // No args == create NULL pointer + if (args.length == 0) { + return new StringCData(subtype, CType.typeOf(subtype), NullMemory.INSTANCE); + } + + byte[] str = args[0].asString().getBytes(); + DirectMemory m = AllocatedNativeMemory.allocate(str.length + 1, false); + m.putZeroTerminatedByteArray(0, str, 0, str.length); + return new StringCData(subtype, CType.typeOf(subtype), m); + } + + @ExposedGet(name = "value") + public PyObject getValue() { + Memory m = getMemory(); + return !m.isNull() + ? Py.newString(new String(m.getZeroTerminatedByteArray(0))) + : Py.None; + } + + + @ExposedSet(name = "value") + public void setValue(PyObject value) { + byte[] str = value.asString().getBytes(); + DirectMemory m = AllocatedNativeMemory.allocate(str.length + 1, false); + m.putZeroTerminatedByteArray(0, str, 0, str.length); + this.memory = m; + if (hasReferenceMemory()) { + getReferenceMemory().putAddress(0, m); + } + } + + @Override + public final String toString() { + return getType().getName() + "(" + getValue().toString() + ")"; + } + + @Override + public String asString() { + Memory m = getMemory(); + return !m.isNull() + ? new String(m.getZeroTerminatedByteArray(0)) + : null; + } + + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Util.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -8,6 +8,8 @@ import org.python.core.PyObject; final class Util { + private static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); + private Util() {} public static final PyObject newSigned8(int value) { @@ -47,6 +49,12 @@ : Py.newInteger(value); } + public static final PyObject newString(long address) { + return address != 0 + ? Py.newString(new String(IO.getZeroTerminatedByteArray(address))) + : Py.None; + } + public static final byte int8Value(PyObject parameter) { return (byte) parameter.asInt(); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-03 15:45:59 UTC (rev 6745) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-04 00:43:55 UTC (rev 6746) @@ -23,6 +23,7 @@ dict.__setitem__("CData", CData.TYPE); dict.__setitem__("PointerCData", PointerCData.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); + dict.__setitem__("StringCData", StringCData.TYPE); dict.__setitem__("Structure", Structure.TYPE); dict.__setitem__("StructLayout", StructLayout.TYPE); dict.__setitem__("FUNCFLAG_STDCALL", Py.newInteger(FUNCFLAG_STDCALL)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |