From: <wme...@us...> - 2009-09-12 01:10:24
|
Revision: 6787 http://jython.svn.sourceforge.net/jython/?rev=6787&view=rev Author: wmeissner Date: 2009-09-12 01:10:11 +0000 (Sat, 12 Sep 2009) Log Message: ----------- Implement some parts of ctypes Array Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CType.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/ArrayCData.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-09-11 11:39:00 UTC (rev 6786) +++ branches/ctypes-jffi/CoreExposed.includes 2009-09-12 01:10:11 UTC (rev 6787) @@ -52,6 +52,7 @@ org/python/modules/_csv/PyWriter.class org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class +org/python/modules/jffi/ArrayCData.class org/python/modules/jffi/ByReference.class org/python/modules/jffi/CData.class org/python/modules/jffi/CType.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-11 11:39:00 UTC (rev 6786) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-12 01:10:11 UTC (rev 6787) @@ -25,8 +25,17 @@ def __mul__(self, len): dict = { '_jffi_type': jffi.Type.Array(self, len) } - return type("%s_%d" % (self.__name__, len), (_ArrayCData,), dict) + # Look back up the stack frame to find out the module this new type is declared in + import inspect + mod = inspect.getmodule(inspect.stack()[1][0]) + if mod is None: + name = "__main__" + else: + name = mod.__name__ + dict["__module__"] = name + return type("%s_Array_%d" % (self.__name__, len), (jffi.ArrayCData, _ArrayCData, _CData), dict) + class _CData(object): @classmethod def in_dll(self, lib, name): @@ -41,9 +50,6 @@ class _ArrayCData(object): - def __init__(self, *args): - raise NotImplementedError("instantiating arrays is not implemented yet") - def __len__(self): return self._jffi_type.length Added: branches/ctypes-jffi/src/org/python/modules/jffi/ArrayCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ArrayCData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ArrayCData.java 2009-09-12 01:10:11 UTC (rev 6787) @@ -0,0 +1,175 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyList; +import org.python.core.PyNewWrapper; +import org.python.core.PyObject; +import org.python.core.PySequenceList; +import org.python.core.PyType; +import org.python.core.SequenceIndexDelegate; +import org.python.expose.ExposedClassMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.ArrayCData", base = CData.class) +public class ArrayCData extends CData implements Pointer { + public static final PyType TYPE = PyType.fromClass(ArrayCData.class); + + final CType.Array arrayType; + final CType componentType; + final MemoryOp componentMemoryOp; + + ArrayCData(PyType subtype, CType.Array arrayType, DirectMemory memory, MemoryOp componentMemoryOp) { + super(subtype, arrayType, memory); + this.arrayType = arrayType; + this.componentType = arrayType.componentType; + this.componentMemoryOp = componentMemoryOp; + } + + @ExposedNew + public static PyObject ArrayCData_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + CType.Array arrayType = getArrayType(subtype); + + // Only clear the array if it is not going to be completely filled + boolean clear = args.length < arrayType.length; + DirectMemory memory = AllocatedNativeMemory.allocateAligned(arrayType.componentType.size() * arrayType.length, + arrayType.componentType.alignment(), clear); + int offset = 0; + for (PyObject value : args) { + arrayType.componentMemoryOp.put(memory, offset, value); + offset += arrayType.componentType.size(); + } + return new ArrayCData(subtype, arrayType, memory, arrayType.componentMemoryOp); + } + + static final CType.Array getArrayType(PyType subtype) { + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + + if (!(jffi_type instanceof CType.Array)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); + } + + return (CType.Array) jffi_type; + } + + @ExposedClassMethod(names= { "from_address" }) + public static final PyObject from_address(PyType subtype, PyObject address) { + + CType.Array arrayType = getArrayType(subtype); + DirectMemory m = Util.getMemoryForAddress(address); + PointerCData cdata = new PointerCData(subtype, arrayType, m.getMemory(0), arrayType.componentMemoryOp); + cdata.setReferenceMemory(m); + + return cdata; + } + + public final DirectMemory getMemory() { + return getReferenceMemory(); + } + + protected final void initReferenceMemory(Memory m) { + // Nothing to do, since the reference memory was initialized during construction + } + + @Override + public PyObject __finditem__(int index) { + return delegator.checkIdxAndFindItem(index); + } + + @Override + public PyObject __getitem__(PyObject index) { + return delegator.checkIdxAndGetItem(index); + } + + @Override + public void __setitem__(int index, PyObject value) { + delegator.checkIdxAndSetItem(index, value); + } + + @Override + public void __setitem__(PyObject index, PyObject value) { + delegator.checkIdxAndSetItem(index, value); + } + + @Override + public void __delitem__(PyObject key) { + throw Py.TypeError("Array does not support item deletion"); + } + + + @Override + public PyObject __iter__() { + return new ArrayIter(); + } + + protected final SequenceIndexDelegate delegator = new SequenceIndexDelegate() { + + @Override + public String getTypeName() { + return getType().fastGetName(); + } + + @Override + public void setItem(int idx, PyObject value) { + componentMemoryOp.put(getReferenceMemory(), idx * componentType.size(), value); + } + + @Override + public void setSlice(int start, int stop, int step, PyObject value) { + if (!(value instanceof PySequenceList)) { + throw Py.TypeError("expected list or tuple"); + } + PySequenceList list = (PySequenceList) value; + for (int i = 0; i < stop - start; ++i) { + setItem(start + i, list.pyget(i)); + } + } + + @Override + public int len() { + return arrayType.length; + } + + @Override + public void delItem(int idx) { + throw Py.TypeError("Array does not support item deletion"); + } + + @Override + public void delItems(int start, int stop) { + throw Py.TypeError("Array does not support item deletion"); + } + + + @Override + public PyObject getItem(int idx) { + return componentMemoryOp.get(getReferenceMemory(), idx * componentType.size()); + } + + @Override + public PyObject getSlice(int start, int stop, int step) { + PyObject[] result = new PyObject[stop - start]; + for (int i = 0; i < result.length; ++i) { + result[i] = getItem(start + i); + } + return new PyList(result); + } + }; + + public class ArrayIter extends PyIterator { + + private int index = 0; + + public PyObject __iternext__() { + if (index >= arrayType.length) { + return null; + } + return componentMemoryOp.get(getReferenceMemory(), index++ * componentType.size()); + } + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-11 11:39:00 UTC (rev 6786) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-12 01:10:11 UTC (rev 6787) @@ -110,15 +110,17 @@ static final class Array extends CType { public static final PyType TYPE = PyType.fromClass(Array.class); final CType componentType; - final PyObject pyComponentType; + final PyType pyComponentType; + final MemoryOp componentMemoryOp; @ExposedGet public final int length; - public Array(PyObject pyComponentType, CType componentType, int length) { + public Array(PyType pyComponentType, CType componentType, int length) { super(NativeType.ARRAY, new com.kenai.jffi.Array(componentType.jffiType, length), null); this.pyComponentType = pyComponentType; this.componentType = componentType; + this.componentMemoryOp = getComponentMemoryOp((PyType) pyComponentType, componentType); this.length = length; } @@ -130,7 +132,11 @@ throw Py.TypeError(String.format("__init__() takes exactly 2 arguments (%d given)", args.length)); } - return new Array(args[0], typeOf(args[0]), args[1].asInt()); + if (!(args[0] instanceof PyType)) { + throw Py.TypeError("invalid component type"); + } + + return new Array((PyType) args[0], typeOf(args[0]), args[1].asInt()); } @Override @@ -142,8 +148,20 @@ public final String toString() { return String.format("<ctypes.Array elem_type=%s length=%d>", pyComponentType.toString(), length); } + + static final MemoryOp getComponentMemoryOp(PyType pyComponentType, CType componentType) { + if (pyComponentType.isSubType(ScalarCData.TYPE)) { + return componentType.getMemoryOp(); + } else if (pyComponentType.isSubType(Structure.TYPE)) { + return new MemoryOp.StructOp(pyComponentType); + } else { + throw Py.TypeError("only scalar and struct types supported"); + } + } } + + @ExposedType(name = "jffi.Type.Pointer", base = CType.class) final static class Pointer extends CType { public static final PyType TYPE = PyType.fromClass(Pointer.class); @@ -166,7 +184,7 @@ } else { throw Py.TypeError("pointer only supported for scalar types"); } - + } @ExposedNew @@ -196,7 +214,7 @@ public final String toString() { return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); } - + private static final class ScalarOp extends MemoryOp { private final MemoryOp op; private final PyType type; @@ -217,12 +235,12 @@ // update the same memory this pointer points to // if (result instanceof ScalarCData) { - ((ScalarCData) result).setReferenceMemory(mem); + ((ScalarCData) result).setReferenceMemory(mem); } return result; } } - + } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-11 11:39:00 UTC (rev 6786) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-12 01:10:11 UTC (rev 6787) @@ -23,6 +23,7 @@ dict.__setitem__("Type", CType.TYPE); dict.__setitem__("Function", Function.TYPE); dict.__setitem__("CData", CData.TYPE); + dict.__setitem__("ArrayCData", ArrayCData.TYPE); dict.__setitem__("PointerCData", PointerCData.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); dict.__setitem__("StringCData", StringCData.TYPE); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |