From: <wme...@us...> - 2009-08-22 10:50:49
|
Revision: 6705 http://jython.svn.sourceforge.net/jython/?rev=6705&view=rev Author: wmeissner Date: 2009-08-22 10:50:40 +0000 (Sat, 22 Aug 2009) Log Message: ----------- First cut of minimal ctypes subset implemented via jffi Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/build.xml branches/ctypes-jffi/src/org/python/modules/Setup.java Added Paths: ----------- branches/ctypes-jffi/Lib/ctypes/ branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/extlibs/jffi-Darwin.jar branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar branches/ctypes-jffi/extlibs/jffi.jar branches/ctypes-jffi/src/org/python/modules/jffi/ 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/DirectMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/Function.java branches/ctypes-jffi/src/org/python/modules/jffi/HeapMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/Invoker.java branches/ctypes-jffi/src/org/python/modules/jffi/Memory.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Type.java branches/ctypes-jffi/src/org/python/modules/jffi/Util.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-22 10:50:40 UTC (rev 6705) @@ -52,6 +52,13 @@ org/python/modules/_csv/PyWriter.class org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class +org/python/modules/jffi/DynamicLibrary.class +org/python/modules/jffi/DynamicLibrary$Symbol.class +org/python/modules/jffi/Function.class +org/python/modules/jffi/Pointer.class +org/python/modules/jffi/ScalarCData.class +org/python/modules/jffi/Type.class +org/python/modules/jffi/Type$Array.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Added: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py (rev 0) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,158 @@ +import jffi + +class _CTypeMetaClass(type): + + def __new__(cls, name, bases, dict): + return type.__new__(cls, name, bases, dict) + + def __mul__(self, len): + return _ArrayType(jffi.Type.Array(self._jffi_type, len)) + +class _ScalarCData(jffi.ScalarCData): + __metaclass__ = _CTypeMetaClass + + def size(self): + return self._jffi_type.size + + size = classmethod(size) + +class _ArrayType(object): + def __init__(self, jffi_type): + self._jffi_type = jffi_type + + def __call__(self, *args): + raise NotImplementedError("instantiating arrays is not implemented yet") + + def __len__(self): + return self._jffi_type.length + +def sizeof(type): + return type._jffi_type.size + +def alignment(type): + return type._jffi_type.alignment + +class c_byte(_ScalarCData): + _jffi_type = jffi.Type.BYTE + +class c_ubyte(_ScalarCData): + _jffi_type = jffi.Type.UBYTE + +class c_short(_ScalarCData): + _jffi_type = jffi.Type.SHORT + +class c_ushort(_ScalarCData): + _jffi_type = jffi.Type.USHORT + +class c_int(_ScalarCData): + _jffi_type = jffi.Type.INT + +class c_uint(_ScalarCData): + _jffi_type = jffi.Type.UINT + +class c_longlong(_ScalarCData): + _jffi_type = jffi.Type.LONGLONG + +class c_ulonglong(_ScalarCData): + _jffi_type = jffi.Type.ULONGLONG + +class c_long(_ScalarCData): + _jffi_type = jffi.Type.LONG + +class c_ulong(_ScalarCData): + _jffi_type = jffi.Type.ULONG + +class c_float(_ScalarCData): + _jffi_type = jffi.Type.FLOAT + +class c_double(_ScalarCData): + _jffi_type = jffi.Type.DOUBLE + +c_int8 = c_byte +c_uint8 = c_ubyte +c_int16 = c_short +c_uint16 = c_ushort +c_int32 = c_int +c_uint32 = c_uint +c_int64 = c_longlong +c_uint64 = c_ulonglong + +c_size_t = c_ulong +c_ssize_t = c_long + +class c_char_p(_ScalarCData): + _jffi_type = jffi.Type.STRING + +class c_void_p(_ScalarCData): + _jffi_type = jffi.Type.POINTER + +class _Function(jffi.Function): + _restype = c_int + _argtypes = None + + def set_restype(self, restype): + self._jffi_restype = restype._jffi_type + self._restype = restype + + def get_restype(self): + return self._restype + + def set_argtypes(self, argtypes): + jffi_types = [] + for t in argtypes: + jffi_types.append(t._jffi_type) + self._jffi_argtypes = jffi_types + self._argtypes = argtypes + + def get_argtypes(self): + return self._argtypes + + restype = property(get_restype, set_restype) + argtypes = property(get_argtypes, set_argtypes) + + +class CDLL: + DEFAULT_MODE = jffi.RTLD_GLOBAL | jffi.RTLD_LAZY + + def __init__(self, name, mode = DEFAULT_MODE, handle = None): + self._handle = jffi.dlopen(name, mode) + + def __getattr__(self, name): + if name.startswith('__') and name.endswith('__'): + raise AttributeError, name + func = self.__getitem__(name) + setattr(self, name, func) + return func + + def __getitem__(self, name): + return _Function(self._handle.find_symbol(name)) + +class LibraryLoader(object): + def __init__(self, dlltype): + self._dlltype = dlltype + + def __getattr__(self, name): + if name[0] == '_': + raise AttributeError(name) + dll = self._dlltype(name) + setattr(self, name, dll) + return dll + + def __getitem__(self, name): + return getattr(self, name) + + def LoadLibrary(self, name): + return self._dlltype(name) + +cdll = LibraryLoader(CDLL) + +# +#class _StructMetaClass(type): +# def __new__(cls, name, bases, dict): +# for attr in dict: +# if attr == '_fields_': +# print "%s has attr %s" % (name, attr) +# return type.__new__(cls, name, bases, dict) +# +#class Structure: +# __metaclass__ = _StructMetaClass Modified: branches/ctypes-jffi/build.xml =================================================================== --- branches/ctypes-jffi/build.xml 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/build.xml 2009-08-22 10:50:40 UTC (rev 6705) @@ -192,6 +192,9 @@ <pathelement path="${extlibs.dir}/constantine-0.4.jar" /> <pathelement path="${extlibs.dir}/jna.jar"/> <pathelement path="${extlibs.dir}/jna-posix.jar"/> + <pathelement path="${extlibs.dir}/jffi.jar"/> + <pathelement path="${extlibs.dir}/jffi-i386-SunOS.jar"/> + <pathelement path="${extlibs.dir}/jffi-x86_64-SunOS.jar"/> </path> <available property="informix.present" classname="com.informix.jdbc.IfxDriver" classpath="${informix.jar}" /> @@ -570,6 +573,9 @@ <zipfileset src="extlibs/asm-util-3.1.jar"/> <rule pattern="org.objectweb.asm.**" result="org.python.objectweb.asm.@1"/> <zipfileset src="extlibs/jna.jar"/> + <zipfileset src="extlibs/jffi.jar"/> + <zipfileset src="extlibs/jffi-i386-SunOS.jar"/> + <zipfileset src="extlibs/jffi-x86_64-SunOS.jar"/> <zipfileset src="extlibs/jna-posix.jar"/> <!-- <rule pattern="com.sun.jna.**" result="org.python.jna.@1"/> --> <rule pattern="org.jruby.ext.posix.**" result="org.python.posix.@1"/> Added: branches/ctypes-jffi/extlibs/jffi-Darwin.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-Darwin.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: branches/ctypes-jffi/extlibs/jffi.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: branches/ctypes-jffi/src/org/python/modules/Setup.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/Setup.java 2009-08-22 07:59:45 UTC (rev 6704) +++ branches/ctypes-jffi/src/org/python/modules/Setup.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -56,6 +56,7 @@ "_systemrestart", "_ast:org.python.antlr.ast.AstModule", "_marshal", - "_threading:org.python.modules._threading._threading" + "_threading:org.python.modules._threading._threading", + "jffi:org.python.modules.jffi.jffi" }; } Added: branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/BoundedNativeMemory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,224 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Platform; + +class BoundedNativeMemory implements Memory, DirectMemory { + protected static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); + protected static final int LONG_SIZE = Platform.getPlatform().longSize(); + protected static final int ADDRESS_SIZE = Platform.getPlatform().addressSize(); + + final long address; + final long size; + final BoundedNativeMemory parent; // keep a reference to avoid the memory being freed + + BoundedNativeMemory(long address, int size) { + this.address = address; + this.size = size; + this.parent = null; + } + + private BoundedNativeMemory(BoundedNativeMemory parent, long offset) { + this.address = parent.address + offset; + this.size = parent.size - offset; + this.parent = parent; + } + + private final void checkBounds(long off, long len) { + Util.checkBounds(size, off, len); + } + + public final long getAddress() { + return address; + } + + public BoundedNativeMemory slice(long offset) { + checkBounds(offset, 1); + return offset == 0 ? this :new BoundedNativeMemory(this, offset); + } + @Override + public final boolean equals(Object obj) { + return (obj instanceof DirectMemory) && ((DirectMemory) obj).getAddress() == address; + } + + @Override + public final int hashCode() { + int hash = 5; + hash = 53 * hash + (int) (this.address ^ (this.address >>> 32)); + return hash; + } + + public final boolean isNull() { + return address == 0; + } + + public final boolean isDirect() { + return true; + } + + public final byte getByte(long offset) { + checkBounds(offset, 1); + return IO.getByte(address + offset); + } + + public final short getShort(long offset) { + checkBounds(offset, 2); + return IO.getShort(address + offset); + } + + public final int getInt(long offset) { + checkBounds(offset, 4); + return IO.getInt(address + offset); + } + + public final long getLong(long offset) { + checkBounds(offset, 8); + return IO.getLong(address + offset); + } + + public final long getNativeLong(long offset) { + return LONG_SIZE == 32 ? getInt(offset) : getLong(offset); + } + + public final float getFloat(long offset) { + checkBounds(offset, 4); + return IO.getFloat(address + offset); + } + + public final double getDouble(long offset) { + checkBounds(offset, 8); + return IO.getDouble(address + offset); + } + + public final long getAddress(long offset) { + checkBounds(offset, ADDRESS_SIZE >> 3); + return IO.getAddress(address + offset); + } + + public final DirectMemory getMemory(long offset) { + checkBounds(offset, ADDRESS_SIZE >> 3); + final long ptr = IO.getAddress(address + offset); + return ptr != 0 ? new NativeMemory(ptr) : null; + } + + public final void putByte(long offset, byte value) { + checkBounds(offset, 1); + IO.putByte(address + offset, value); + } + + public final void putShort(long offset, short value) { + checkBounds(offset, 2); + IO.putShort(address + offset, value); + } + + public final void putInt(long offset, int value) { + checkBounds(offset, 4); + IO.putInt(address + offset, value); + } + + public final void putLong(long offset, long value) { + checkBounds(offset, 8); + IO.putLong(address + offset, value); + } + + public final void putNativeLong(long offset, long value) { + if (LONG_SIZE == 32) { + putInt(offset, (int) value); + } else { + putLong(offset, value); + } + } + public final void putAddress(long offset, long value) { + checkBounds(offset, ADDRESS_SIZE >> 3); + IO.putAddress(address + offset, value); + } + public final void putFloat(long offset, float value) { + checkBounds(offset, 4); + IO.putFloat(address + offset, value); + } + + public final void putDouble(long offset, double value) { + checkBounds(offset, 8); + IO.putDouble(address + offset, value); + } + + public final void putAddress(long offset, Memory value) { + checkBounds(offset, ADDRESS_SIZE >> 3); + IO.putAddress(address + offset, ((DirectMemory) value).getAddress()); + } + + public final void get(long offset, byte[] dst, int off, int len) { + checkBounds(offset, len); + IO.getByteArray(address + offset, dst, off, len); + } + + public final void put(long offset, byte[] src, int off, int len) { + checkBounds(offset, len); + IO.putByteArray(address + offset, src, off, len); + } + + public final void get(long offset, short[] dst, int off, int len) { + checkBounds(offset, len << 1); + IO.getShortArray(address + offset, dst, off, len); + } + + public final void put(long offset, short[] src, int off, int len) { + checkBounds(offset, len << 1); + IO.putShortArray(address + offset, src, off, len); + } + + public final void get(long offset, int[] dst, int off, int len) { + checkBounds(offset, len << 2); + IO.getIntArray(address + offset, dst, off, len); + } + + public final void put(long offset, int[] src, int off, int len) { + checkBounds(offset, len << 2); + IO.putIntArray(address + offset, src, off, len); + } + + public final void get(long offset, long[] dst, int off, int len) { + checkBounds(offset, len << 3); + IO.getLongArray(address + offset, dst, off, len); + } + + public final void put(long offset, long[] src, int off, int len) { + checkBounds(offset, len << 3); + IO.putLongArray(address + offset, src, off, len); + } + + public final void get(long offset, float[] dst, int off, int len) { + checkBounds(offset, len << 2); + IO.getFloatArray(address + offset, dst, off, len); + } + + public final void put(long offset, float[] src, int off, int len) { + checkBounds(offset, len << 2); + IO.putFloatArray(address + offset, src, off, len); + } + + public final void get(long offset, double[] dst, int off, int len) { + checkBounds(offset, len << 3); + IO.getDoubleArray(address + offset, dst, off, len); + } + + public final void put(long offset, double[] src, int off, int len) { + checkBounds(offset, len << 3); + IO.putDoubleArray(address + offset, src, off, len); + } + + public final int indexOf(long offset, byte value) { + return value == 0 + ? (int) IO.getStringLength(address + offset) + : (int) IO.indexOf(address + offset, value); + } + + public final int indexOf(long offset, byte value, int maxlen) { + return (int) IO.indexOf(address, value, maxlen); + } + + public final void setMemory(long offset, long size, byte value) { + checkBounds(offset, size); + IO.setMemory(address + offset, size, value); + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,433 @@ +package org.python.modules.jffi; + +import com.kenai.jffi.ArrayFlags; +import com.kenai.jffi.Function; +import com.kenai.jffi.HeapInvocationBuffer; +import com.kenai.jffi.Platform; +import org.python.core.Py; +import org.python.core.PyNone; +import org.python.core.PyObject; + +class DefaultInvokerFactory { + private static final class SingletonHolder { + public static final DefaultInvokerFactory INSTANCE = new DefaultInvokerFactory(); + } + + public static final DefaultInvokerFactory getFactory() { + return SingletonHolder.INSTANCE; + } + + private DefaultInvokerFactory() {} + + final Invoker createInvoker(com.kenai.jffi.Function function, Type[] parameterTypes, Type returnType) { + ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length]; + + for (int i = 0; i < marshallers.length; ++i) { + marshallers[i] = getMarshaller(parameterTypes[i]); + } + + + if (returnType instanceof Type.Builtin) { + switch (returnType.getNativeType()) { + case VOID: + return new VoidInvoker(function, marshallers); + + case BYTE: + return new Signed8Invoker(function, marshallers); + + case UBYTE: + return new Unsigned8Invoker(function, marshallers); + + case SHORT: + return new Signed16Invoker(function, marshallers); + + case USHORT: + return new Unsigned16Invoker(function, marshallers); + + case INT: + return new Signed32Invoker(function, marshallers); + + case UINT: + return new Unsigned32Invoker(function, marshallers); + + case LONGLONG: + return new Signed64Invoker(function, marshallers); + + case ULONGLONG: + return new Unsigned64Invoker(function, marshallers); + + case LONG: + return Platform.getPlatform().longSize() == 32 + ? new Signed32Invoker(function, marshallers) + : new Signed64Invoker(function, marshallers); + + case ULONG: + return Platform.getPlatform().longSize() == 32 + ? new Unsigned32Invoker(function, marshallers) + : new Unsigned64Invoker(function, marshallers); + case FLOAT: + return new FloatInvoker(function, marshallers); + + case DOUBLE: + return new DoubleInvoker(function, marshallers); + + case POINTER: + return new PointerInvoker(function, marshallers); + + default: + break; + } + } + throw Py.RuntimeError("Unsupported return type: " + returnType); + + } + + private static final ParameterMarshaller getMarshaller(NativeType type) { + switch (type) { + + case BYTE: + return Signed8Marshaller.INSTANCE; + case UBYTE: + return Unsigned8Marshaller.INSTANCE; + + case SHORT: + return Signed16Marshaller.INSTANCE; + case USHORT: + return Unsigned16Marshaller.INSTANCE; + + case INT: + return Signed32Marshaller.INSTANCE; + case UINT: + return Unsigned32Marshaller.INSTANCE; + + case LONGLONG: + return Signed64Marshaller.INSTANCE; + case ULONGLONG: + return Unsigned64Marshaller.INSTANCE; + + case LONG: + return Platform.getPlatform().longSize() == 32 + ? Signed32Marshaller.INSTANCE : Signed64Marshaller.INSTANCE; + case ULONG: + return Platform.getPlatform().longSize() == 32 + ? Unsigned32Marshaller.INSTANCE : Unsigned64Marshaller.INSTANCE; + + case FLOAT: + return FloatMarshaller.INSTANCE; + + case DOUBLE: + return DoubleMarshaller.INSTANCE; + + case POINTER: + return PointerMarshaller.INSTANCE; + + case STRING: + return StringMarshaller.INSTANCE; + default: + throw Py.RuntimeError("Unsupported parameter type: " + type); + } + } + + private static final ParameterMarshaller getMarshaller(Type type) { + if (type instanceof Type.Builtin) { + return getMarshaller(type.getNativeType()); + } else { + throw Py.RuntimeError("Unsupported parameter type: " + type); + } + } + + private static interface ParameterMarshaller { + void marshal(HeapInvocationBuffer buffer, PyObject arg); + } + + private static abstract class BaseInvoker implements Invoker { + final Function jffiFunction; + final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance(); + final ParameterMarshaller[] marshallers; + final int arity; + + public BaseInvoker(Function function, ParameterMarshaller[] marshallers) { + this.jffiFunction= function; + this.marshallers = marshallers; + this.arity = marshallers.length; + } + + final HeapInvocationBuffer convertArguments(PyObject[] args) { + checkArity(args); + HeapInvocationBuffer buffer = new HeapInvocationBuffer(jffiFunction); + + for (int i = 0; i < marshallers.length; ++i) { + marshallers[i].marshal(buffer, args[i]); + } + + return buffer; + } + + public final PyObject invoke() { + return invoke(new PyObject[0]); + } + + public final PyObject invoke(PyObject arg0) { + return invoke(new PyObject[] { arg0 }); + } + + public final PyObject invoke(PyObject arg0, PyObject arg1) { + return invoke(new PyObject[] { arg0, arg1 }); + } + + public final PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return invoke(new PyObject[] { arg0, arg1, arg2 }); + } + + final void checkArity(PyObject[] args) { + checkArity(args.length); + } + + final void checkArity(int got) { + if (got != arity) { + throw Py.TypeError(String.format("expected %d args; got %d", arity, got)); + } + } + } + + private static final class VoidInvoker extends BaseInvoker { + + public VoidInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + jffiInvoker.invokeInt(jffiFunction, convertArguments(args)); + + return Py.None; + } + + } + private static final class Signed8Invoker extends BaseInvoker { + + public Signed8Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned8(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned8Invoker extends BaseInvoker { + + public Unsigned8Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned8(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed16Invoker extends BaseInvoker { + + public Signed16Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned16(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned16Invoker extends BaseInvoker { + + public Unsigned16Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned16(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed32Invoker extends BaseInvoker { + + public Signed32Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned32(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned32Invoker extends BaseInvoker { + + public Unsigned32Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned32(jffiInvoker.invokeInt(jffiFunction, convertArguments(args))); + } + } + + private static final class Signed64Invoker extends BaseInvoker { + + public Signed64Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newSigned64(jffiInvoker.invokeLong(jffiFunction, convertArguments(args))); + } + } + + private static final class Unsigned64Invoker extends BaseInvoker { + + public Unsigned64Invoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Util.newUnsigned64(jffiInvoker.invokeLong(jffiFunction, convertArguments(args))); + } + } + + private static final class FloatInvoker extends BaseInvoker { + + public FloatInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newFloat(jffiInvoker.invokeFloat(jffiFunction, convertArguments(args))); + } + } + + private static final class DoubleInvoker extends BaseInvoker { + + public DoubleInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newFloat(jffiInvoker.invokeDouble(jffiFunction, convertArguments(args))); + } + } + + private static final class PointerInvoker extends BaseInvoker { + + public PointerInvoker(Function function, ParameterMarshaller[] marshallers) { + super(function, marshallers); + } + + public final PyObject invoke(PyObject[] args) { + return Py.newLong(jffiInvoker.invokeAddress(jffiFunction, convertArguments(args))); + } + } + + /*------------------------------------------------------------------------*/ + static abstract class BaseMarshaller implements ParameterMarshaller { + } + + private static class Signed8Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed8Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putByte(Util.int8Value(arg)); + } + } + + private static class Unsigned8Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned8Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putByte((byte) Util.uint8Value(arg)); + } + } + + private static class Signed16Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed16Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putShort(Util.int16Value(arg)); + } + } + + private static class Unsigned16Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned16Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putShort((short) Util.uint16Value(arg)); + } + } + + private static class Signed32Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed32Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putInt(Util.int32Value(arg)); + } + } + + private static class Unsigned32Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned32Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putInt((int) Util.int32Value(arg)); + } + } + + private static class Signed64Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Signed64Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putLong(Util.int64Value(arg)); + } + } + + private static class Unsigned64Marshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new Unsigned64Marshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putLong(Util.uint64Value(arg)); + } + } + + private static class FloatMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new FloatMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putFloat((float) arg.asDouble()); + } + } + + private static class DoubleMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new DoubleMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject arg) { + buffer.putDouble(arg.asDouble()); + } + } + + private static class StringMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new StringMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { + if (parameter instanceof PyNone) { + buffer.putAddress(0); + } else { + byte[] bytes = parameter.toString().getBytes(); + buffer.putArray(bytes, 0, bytes.length, + ArrayFlags.IN | ArrayFlags.NULTERMINATE); + } + } + } + + private static class PointerMarshaller extends BaseMarshaller { + public static final ParameterMarshaller INSTANCE = new PointerMarshaller(); + + public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { + throw Py.NotImplementedError("POINTER parameters not implemented"); + } + } + +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DirectMemory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,6 @@ + +package org.python.modules.jffi; + +public interface DirectMemory extends Memory { + long getAddress(); +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,86 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Library; +import org.python.core.ClassDictInit; +import org.python.core.Py; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposeAsSuperclass; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.DynamicLibrary", base = PyObject.class) +public class DynamicLibrary extends PyObject { + + public static final PyType TYPE = PyType.fromClass(DynamicLibrary.class); + + @ExposedGet + public final String name; + private final com.kenai.jffi.Library lib; + + DynamicLibrary(String libname, int mode) { + this.name = libname; + lib = Library.getCachedInstance(libname, mode); + + if (lib == null) { + throw Py.RuntimeError("Could not open " + + libname != null ? libname : "[current process]" + + " " + Library.getLastError()); + } + } + + private long findSymbol(PyObject name) { + long address = lib.getSymbolAddress(name.asString()); + if (address == 0) { + throw Py.NameError("Could not locate symbol '" + name.asString() + "' in " + this.name); + } + + return address; + } + + @ExposedMethod + public final PyObject find_symbol(PyObject name) { + long address = findSymbol(name); + return new Symbol(this, name.asString(), address, new NativeMemory(address)); + } + + @ExposedMethod + public final PyObject find_function(PyObject name) { + return new TextSymbol(this, name.asString(), findSymbol(name)); + } + + @ExposedMethod + public final PyObject find_variable(PyObject name) { + return new DataSymbol(this, name.asString(), findSymbol(name)); + } + + @ExposedType(name = "jffi.DynamicLibrary.Symbol", base = Pointer.class) + public static class Symbol extends Pointer { + public static final PyType TYPE = PyType.fromClass(Symbol.class); + + final DynamicLibrary library; + + @ExposedGet + public final String name; + + public Symbol(DynamicLibrary library, String name, long address, DirectMemory memory) { + super(address, memory); + this.library = library; + this.name = name; + } + } + + public static class TextSymbol extends Symbol implements ExposeAsSuperclass { + public TextSymbol(DynamicLibrary lib, String name, long address) { + super(lib, name, address, new NativeMemory(address)); + } + } + + public static class DataSymbol extends Symbol implements ExposeAsSuperclass { + public DataSymbol(DynamicLibrary lib, String name, long address) { + super(lib, name, address, new NativeMemory(address)); + } + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-08-22 10:50:40 UTC (rev 6705) @@ -0,0 +1,647 @@ + +package org.python.modules.jffi; + +import com.kenai.jffi.Function; +import com.kenai.jffi.Platform; +import org.python.core.Py; +import org.python.core.PyObject; + + +/** + * A factory which generates {@link Invoker} instances that are optimized for + * 32 bit integer and float parameters / result types with 3 or less parameters. + * + * Technical background: Instead of trying to cram all calls down a generic call + * path, then figuring out how to convert the parameters in the native code on + * each call, jffi supplies arity and type specific call paths that can be + * optimized ahead of time by the native code. + * + * The downside of this approach is more java code to wire up the functions and + * call them using the arity+type specific paths, but in the case of int and float + * parameters, it can result in more than a 100% speed boost over the generic path. + */ +public class FastIntInvokerFactory { + private static final class SingletonHolder { + private static final FastIntInvokerFactory INSTANCE = new FastIntInvokerFactory(); + } + + private FastIntInvokerFactory() {} + + public static final FastIntInvokerFactory getFactory() { + return SingletonHolder.INSTANCE; + } + + /** + * Interface used to convert from a python object to a native integer + */ + private static interface IntParameterConverter { + int intValue(PyObject value); + } + + /** + * Interface used to convert from a native integer to a python object + */ + private static interface IntResultConverter { + PyObject pyValue(int value); + } + + /** + * Tests if a combination of result and parameter types can be called using + * an {@link Invoker} created by this factory. + * + * @param returnType The return type of the native function. + * @param parameterTypes The parameter types of the native function. + * @return <tt>true</tt> if the method can be handled as a fast int method. + */ + final boolean isFastIntMethod(Type returnType, Type[] parameterTypes) { + for (int i = 0; i < parameterTypes.length; ++i) { + if (!isFastIntParam(parameterTypes[i])) { + return false; + } + } + return parameterTypes.length <= 3 && isFastIntResult(returnType); + } + + /** + * Tests if the type can be returned as an integer result. + * + * @param type The result type. + * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer. + */ + final boolean isFastIntResult(Type type) { + if (type instanceof Type.Builtin) { + switch (type.getNativeType()) { + case VOID: + case BYTE: + case UBYTE: + case SHORT: + case USHORT: + case INT: + case UINT: + return true; + + case LONG: + case ULONG: + return Platform.getPlatform().longSize() == 32; + + case FLOAT: + return Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64; + } + } + return false; + } + + + /** + * Tests if the type can be passed as an integer parameter. + * + * @param type The parameter type. + * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer. + */ + final boolean isFastIntParam(Type paramType) { + if (paramType instanceof Type.Builtin) { + switch (paramType.getNativeType()) { + case BYTE: + case UBYTE: + case SHORT: + case USHORT: + case INT: + case UINT: + return true; + + case LONG: + case ULONG: + return Platform.getPlatform().longSize() == 32; + + case FLOAT: + return Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64; + } + } + return false; + } + + + /** + * Creates a new <tt>Invoker</tt> instance for the given function, with the + * given parameter types and return type. + * + * @param function The JFFI function to wrap + * @param parameterTypes The parameter types the function will be called with + * @param returnType The result type the function will return + * @return A new {@link Invoker} instance. + */ + final Invoker createInvoker(Function function, Type[] parameterTypes, Type returnType) { + IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length]; + + for (int i = 0; i < parameterConverters.length; ++i) { + parameterConverters[i] = getIntParameterConverter(parameterTypes[i]); + } + if (returnType.nativeType == NativeType.FLOAT) { + switch (parameterTypes.length) { + case 0: + return new FastFloatInvokerZero(function, null, parameterConverters); + case 1: + return new FastFloatInvokerOne(function, null, parameterConverters); + case 2: + return new FastFloatInvokerTwo(function, null, parameterConverters); + case 3: + return new FastFloatInvokerThree(function, null, parameterConverters); + } + } else { + IntResultConverter resultConverter = getIntResultConverter(returnType); + switch (parameterTypes.length) { + case 0: + return new FastIntInvokerZero(function, resultConverter, parameterConverters); + case 1: + return new FastIntInvokerOne(function, resultConverter, parameterConverters); + case 2: + return new FastIntInvokerTwo(function, resultConverter, parameterConverters); + case 3: + return new FastIntInvokerThree(function, resultConverter, parameterConverters); + } + } + throw Py.RuntimeError("Fast Integer invoker does not support functions with arity=" + parameterTypes.length); + } + + /** + * Gets a python object to integer parameter converter. + * + * @param type The python C type + * @return An <tt>IntParameterConverter</tt> instance. + */ + final IntParameterConverter getIntParameterConverter(Type type) { + if (type instanceof Type.Builtin) { + return getIntParameterConverter(type.getNativeType()); + } + throw Py.TypeError("cannot convert objects of type " + type + " to int"); + } + + + /** + * Gets a python object to integer parameter converter. + * + * @param type The object type. + * @return An <tt>IntParameterConverter</tt> instance. + */ + final IntParameterConverter getIntParameterConverter(NativeType type) { + switch (type) { + case BYTE: + return Signed8ParameterConverter.INSTANCE; + + case UBYTE: + return Unsigned8ParameterConverter.INSTANCE; + + case SHORT: + return Signed16ParameterConverter.INSTANCE; + + case USHORT: + return Unsigned16ParameterConverter.INSTANCE; + + case INT: + return Signed32ParameterConverter.INSTANCE; + + case UINT: + return Unsigned32ParameterConverter.INSTANCE; + + case LONG: + if (Platform.getPlatform().longSize() == 32) { + return Signed32ParameterConverter.INSTANCE; + } + break; + + case ULONG: + if (Platform.getPlatform().longSize() == 32) { + return Unsigned32ParameterConverter.INSTANCE; + } + break; + + case FLOAT: + if (Platform.getPlatform().getCPU() == Platform.CPU.I386 + || Platform.getPlatform().getCPU() == Platform.CPU.X86_64) { + return Float32ParameterConverter.INSTANCE; + } + break; + default: + break; + } + + throw Py.TypeError("cannot convert objects of type " + type + " to int"); + } + + + /** + * Gets a int to python object result converter for the type. + * + * @param type The object type. + * @return An <tt>IntResultConverter</tt> instance. + */ + final IntResultConverter getIntResultConverter(Type type) { + return type instanceof Type.Builtin ? getIntResultConverter(type.getNativeType()) : null; + } + + + /** + * Gets a int to python object result converter for the type. + * + * @param type The object type. + * @return An <tt>IntResultConverter</tt> instance. + */ + final IntResultConverter getIntResultConverter(NativeType type) { + switch (type) { + case VOID: + return VoidResultConverter.INSTANCE; + + case BYTE: + return Signed8ResultConverter.INSTANCE; + + case UBYTE: + return Unsigned8ResultConverter.INSTANCE; + + case SHORT: + return Signed16ResultConverter.INSTANCE; + + case USHORT: + return Unsigned16ResultConverter.INSTANCE; + + case INT: + return Signed32ResultConverter.INSTANCE; + + case UINT: + return Unsigned32ResultConverter.INSTANCE; + + case LONG: + if (Platform.getPlatform().longSize() == 32) { + return Signed32ResultConverter.INSTANCE; + } + break; + + case ULONG: + if (Platform.getPlatform().longSize() == 32) { + return Unsigned32ResultConverter.INSTANCE; + } + break; + + default: + break; + } + throw new IllegalArgumentException("Cannot convert objects of type " + type + " from int"); + } + + /** + * Base class for all fast-int {@link Invoker} subclasses + */ + private static abstract class BaseFastIntInvoker implements Invoker { + final com.kenai.jffi.Invoker jffiInvoker = com.kenai.jffi.Invoker.getInstance(); + final Function function; + final IntResultConverter resultConverter; + final int arity; + final IntParameterConverter c0, c1, c2; + + BaseFastIntInvoker(Function function, IntResultConverter resultConverter, + IntParameterConverter[] parameterConverters) { + this.function = function; + this.resultConverter = resultConverter; + this.arity = parameterConverters.length; + c0 = parameterConverters.length > 0 ? parameterConverters[0] : null; + c1 = parameterConverters.length > 1 ? parameterConverters[1] : null; + c2 = parameterConverters.length > 2 ? parameterConverters[2] : null; + } + + final void checkArity(PyObject[] args) { + checkArity(args.length); + } + + final void checkArity(int got) { + if (got != arity) { + throw Py.TypeError(String.format("__call__() takes exactly %d arguments (%d given)", arity, got)); + } + } + public PyObject invoke(PyObject[] args) { + checkArity(args); + switch (arity) { + case 0: + return invoke(); + case 1: + return invoke(args[0]); + case 2: + return invoke(args[0], args[1]); + case 3: + return invoke(args[0], args[1], args[2]); + default: + throw Py.RuntimeError("invalid fast-int arity"); + } + } + + public PyObject invoke() { + checkArity(0); + return Py.None; + } + + public PyObject invoke(PyObject arg1) { + checkArity(1); + return Py.None; + } + + public PyObject invoke(PyObject arg1, PyObject arg2) { + checkArity(2); + return Py.None; + } + + public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) { + checkArity(3); + return Py.None; + } + + } + + /** + * Fast-int invoker that takes no parameters. + */ + private static final class FastIntInvokerZero extends BaseFastIntInvoker { + + public FastIntInvokerZero(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke() { + return resultConverter.pyValue(jffiInvoker.invokeVrI(function)); + } + } + + /** + * Fast-int invoker that takes a single parameter + */ + private static final class FastIntInvokerOne extends BaseFastIntInvoker { + public FastIntInvokerOne(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + + } + + @Override + public final PyObject invoke(PyObject arg0) { + return resultConverter.pyValue(jffiInvoker.invokeIrI(function, + c0.intValue(arg0))); + } + } + + + /** + * Fast-int invoker that takes two parameters + */ + private static final class FastIntInvokerTwo extends BaseFastIntInvoker { + + public FastIntInvokerTwo(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1) { + return resultConverter.pyValue(jffiInvoker.invokeIIrI(function, + c0.intValue(arg0), c1.intValue(arg1))); + } + } + + /** + * Fast-int invoker that takes three parameters + */ + private static final class FastIntInvokerThree extends BaseFastIntInvoker { + + public FastIntInvokerThree(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return resultConverter.pyValue(jffiInvoker.invokeIIIrI(function, + c0.intValue(arg0), c1.intValue(arg1), c2.intValue(arg2))); + } + } + + /** + * Fast-int invoker that takes no parameters and returns a float + */ + private static final class FastFloatInvokerZero extends BaseFastIntInvoker { + + public FastFloatInvokerZero(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke() { + return Py.newFloat(jffiInvoker.invokeVrF(function)); + } + } + + /** + * Fast-int invoker that takes one parameter and returns a float + */ + private static final class FastFloatInvokerOne extends BaseFastIntInvoker { + + public FastFloatInvokerOne(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public final PyObject invoke(PyObject arg0) { + return Py.newFloat(jffiInvoker.invokeIrF(function, + c0.intValue(arg0))); + } + } + + + /** + * Fast-int invoker that takes two parameters and returns a float + */ + private static final class FastFloatInvokerTwo extends BaseFastIntInvoker { + + public FastFloatInvokerTwo(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1) { + return Py.newFloat(jffiInvoker.invokeIIrF(function, + c0.intValue(arg0), c1.intValue(arg1))); + } + } + + /** + * Fast-int invoker that takes three parameters and returns a float + */ + private static final class FastFloatInvokerThree extends BaseFastIntInvoker { + + public FastFloatInvokerThree(Function function, IntResultConverter resultConverter, + IntParameterConverter parameterConverters[]) { + super(function, resultConverter, parameterConverters); + } + + @Override + public PyObject invoke(PyObject arg0, PyObject arg1, PyObject arg2) { + return Py.newFloat(jffiInvoker.invokeIIIrF(function, + c0.intValue(arg0), c1.intValue(arg1), c2.intValue(arg2))); + } + } + + /** + * Base class for all fast-int result converters + */ + static abstract class BaseResultConverter implements IntResultConverter { + + } + + /** + * Converts a native void result into into a python None instance + */ + static final class VoidResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new VoidResultConverter(); + public final PyObject pyValue(int value) { + return Py.None; + } + } + + /** + * Converts a native signed byte result into into a python integer instance + */ + static final class Signed8ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed8ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned8(value); + } + } + + /** + * Converts a native unsigned byte result into into a python integer instance + */ + static final class Unsigned8ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned8ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned8(value); + } + } + + /** + * Converts a native signed short result into into a python integer instance + */ + static final class Signed16ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed16ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned16(value); + } + } + + /** + * Converts a native unsigned short result into into a python integer instance + */ + static final class Unsigned16ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned16ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned16(value); + } + } + + /** + * Converts a native signed int result into into a python integer instance + */ + static final class Signed32ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Signed32ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newSigned32(value); + } + } + + /** + * Converts a native unsigned int result into into a python integer instance + */ + static final class Unsigned32ResultConverter extends BaseResultConverter { + public static final IntResultConverter INSTANCE = new Unsigned32ResultConverter(); + public final PyObject pyValue(int value) { + return Util.newUnsigned32(value); + } + } + + /** + * Base class for all integer parameter converters. + */ + static abstract class BaseParameterConverter implements IntParameterConverter { + } + + /** + * Converter for python signed byte to native int + */ + static final class Signed8ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed8ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int8Value(obj); + } + } + + /** + * Converter for python unsigned byte to native int + */ + static final class Unsigned8ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Unsigned8ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.uint8Value(obj); + } + } + + /** + * Converter for python signed short to native int + */ + static final class Signed16ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed16ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int16Value(obj); + } + } + + /** + * Converter for python unsigned short to native int + */ + static final class Unsigned16ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Unsigned16ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.uint16Value(obj); + } + } + + /** + * Converter for python signed int to native int + */ + static final class Signed32ParameterConverter extends BaseParameterConverter { + public static final IntParameterConverter INSTANCE = new Signed32ParameterConverter(); + public final int intValue(PyObject obj) { + return Util.int32Value(obj); + } + } + + /** + * Converter for python unsigned int to native int + */ + static final class Unsigned32ParameterConverter extends BaseParameterConverter { + ... [truncated message content] |
From: <wme...@us...> - 2009-08-26 05:25:27
|
Revision: 6720 http://jython.svn.sourceforge.net/jython/?rev=6720&view=rev Author: wmeissner Date: 2009-08-26 05:25:19 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Experimental implementation of pointer and byref Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Type.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-26 05:25:19 UTC (rev 6720) @@ -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/CData.class org/python/modules/jffi/DynamicLibrary.class org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class @@ -59,6 +60,7 @@ org/python/modules/jffi/ScalarCData.class org/python/modules/jffi/Type.class org/python/modules/jffi/Type$Array.class +org/python/modules/jffi/Type$Pointer.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-26 05:25:19 UTC (rev 6720) @@ -32,6 +32,15 @@ def alignment(type): return type._jffi_type.alignment +def byref(cdata): + return cdata.byref() + +def pointer(cdata): + return cdata.pointer() + +def POINTER(type): + return jffi.Type.Pointer(type._jffi_type, type) + class c_byte(_ScalarCData): _jffi_type = jffi.Type.BYTE Added: branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedDirectMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,7 @@ + +package org.python.modules.jffi; + +public interface AllocatedDirectMemory extends DirectMemory { + public void free(); + public void setAutoRelease(boolean autorelease); +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/AllocatedNativeMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,67 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; + +class AllocatedNativeMemory extends BoundedNativeMemory implements AllocatedDirectMemory { + private volatile boolean released = false; + private volatile boolean autorelease = true; + + /** The real memory address */ + private final long storage; + + /** + * Allocates native memory + * + * @param size The number of bytes to allocate + * @param clear Whether the memory should be cleared (zeroed) + * @return A new {@link AllocatedDirectMemory} + */ + static final AllocatedNativeMemory allocate(int size, boolean clear) { + return allocateAligned(size, 1, clear); + } + + /** + * Allocates native memory, aligned to a minimum boundary. + * + * @param size The number of bytes to allocate + * @param align The minimum alignment of the memory + * @param clear Whether the memory should be cleared (zeroed) + * @return A new {@link AllocatedDirectMemory} + */ + static final AllocatedNativeMemory allocateAligned(int size, int align, boolean clear) { + long memory = IO.allocateMemory(size + align - 1, clear); + if (memory == 0) { + throw Py.RuntimeError("failed to allocate " + size + " bytes"); + } + return new AllocatedNativeMemory(memory, size, align); + } + + private AllocatedNativeMemory(long address, int size, int align) { + super(((address - 1) & ~(align - 1)) + align, size); + this.storage = address; + } + + public void free() { + if (!released) { + IO.freeMemory(storage); + released = true; + } + } + + public void setAutoRelease(boolean release) { + this.autorelease = release; + } + + @Override + protected void finalize() throws Throwable { + try { + if (!released && autorelease) { + IO.freeMemory(storage); + released = true; + } + } finally { + super.finalize(); + } + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,80 @@ + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedSet; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.CData", base = PyObject.class) +public abstract class CData extends PyObject { + public static final PyType TYPE = PyType.fromClass(CData.class); + + final MemoryOp memoryOp; + final Type type; + + private Memory contentMemory; + private PyObject value; + + CData(PyType subtype, Type type, MemoryOp memoryOp) { + super(subtype); + this.type = type; + this.memoryOp = memoryOp; + this.value = Py.None; + this.contentMemory = null; + } + + @ExposedGet(name = "value") + public PyObject getValue() { + // If native memory has been allocated, read the value from there + if (contentMemory != null) { + return memoryOp.get(contentMemory, 0); + } + + return value; + } + + + @ExposedSet(name = "value") + public void setValue(PyObject value) { + this.value = value; + // If native memory has been allocated, sync the value to memory + if (contentMemory != null) { + memoryOp.put(contentMemory, 0, value); + } + } + + @ExposedMethod(names= { "byref", "pointer" }) + public PyObject byref() { + return new Pointer((DirectMemory) getContentMemory(), memoryOp); + } + + boolean hasValueMemory() { + return contentMemory != null; + } + + void setContentMemory(Memory memory) { + if (!(memory instanceof DirectMemory)) { + throw Py.TypeError("invalid memory"); + } + this.contentMemory = memory; + } + + Memory getContentMemory() { + if (contentMemory != null) { + return contentMemory; + } + + return allocateDirect(); + } + + private DirectMemory allocateDirect() { + DirectMemory m = AllocatedNativeMemory.allocate(type.size(), false); + memoryOp.put(m, 0, value); + contentMemory = m; + return m; + } +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -426,7 +426,11 @@ public static final ParameterMarshaller INSTANCE = new PointerMarshaller(); public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { - throw Py.NotImplementedError("POINTER parameters not implemented"); + if (parameter instanceof Pointer) { + buffer.putAddress(((Pointer) parameter).address); + } else { + throw Py.TypeError("expected pointer argument"); + } } } Added: branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/InvalidMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,182 @@ + + +package org.python.modules.jffi; + +import org.python.core.Py; +import org.python.core.PyException; + +/** + * An implementation of Memory that throws an exception on any access. + */ +public abstract class InvalidMemory implements Memory { + private final String message; + + public InvalidMemory(String message) { + this.message = message; + } + + protected PyException ex() { + return Py.MemoryError(message); + } + + public Memory slice(long offset) { + return this; + } + + public java.nio.ByteBuffer asByteBuffer() { + throw ex(); + } + + public final byte getByte(long offset) { + throw ex(); + } + + public final short getShort(long offset) { + throw ex(); + } + + public final int getInt(long offset) { + throw ex(); + } + + public final long getLong(long offset) { + throw ex(); + } + + public final long getNativeLong(long offset) { + throw ex(); + } + + public final float getFloat(long offset) { + throw ex(); + } + + public final double getDouble(long offset) { + throw ex(); + } + + public final DirectMemory getMemory(long offset) { + throw ex(); + } + + public final long getAddress(long offset) { + throw ex(); + } + + public final void putByte(long offset, byte value) { + throw ex(); + } + + public final void putShort(long offset, short value) { + throw ex(); + } + + public final void putInt(long offset, int value) { + throw ex(); + } + + public final void putLong(long offset, long value) { + throw ex(); + } + + public final void putNativeLong(long offset, long value) { + throw ex(); + } + + public final void putFloat(long offset, float value) { + throw ex(); + } + + public final void putDouble(long offset, double value) { + throw ex(); + } + + public final void putMemory(long offset, Memory value) { + throw ex(); + } + + public final void putAddress(long offset, long value) { + throw ex(); + } + + public final void putAddress(long offset, Memory value) { + throw ex(); + } + + public final void get(long offset, byte[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, byte[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, short[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, short[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, int[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, int[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, long[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, long[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, float[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, float[] src, int off, int len) { + throw ex(); + } + + public final void get(long offset, double[] dst, int off, int len) { + throw ex(); + } + + public final void put(long offset, double[] src, int off, int len) { + throw ex(); + } + + public final int indexOf(long offset, byte value) { + throw ex(); + } + + public final int indexOf(long offset, byte value, int maxlen) { + throw ex(); + } + + public final void setMemory(long offset, long size, byte value) { + throw ex(); + } + + public final void clear() { + throw ex(); + } + + public byte[] getZeroTerminatedByteArray(long offset) { + throw ex(); + } + + public byte[] getZeroTerminatedByteArray(long offset, int maxlen) { + throw ex(); + } + + public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) { + throw ex(); + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -8,6 +8,7 @@ * Defines memory operations for a primitive type */ abstract class MemoryOp { + public static final MemoryOp INVALID = new InvalidOp(); public static final MemoryOp VOID = new VoidOp(); public static final MemoryOp INT8 = new Signed8(); public static final MemoryOp UINT8 = new Unsigned8(); @@ -64,6 +65,16 @@ abstract PyObject get(Memory mem, long offset); abstract void put(Memory mem, long offset, PyObject value); + private static final class InvalidOp extends MemoryOp { + public final void put(Memory mem, long offset, PyObject value) { + throw Py.TypeError("invalid memory access"); + } + + public final PyObject get(Memory mem, long offset) { + throw Py.TypeError("invalid memory access"); + } + } + private static final class VoidOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { throw Py.TypeError("Attempting to write void to memory"); @@ -166,11 +177,16 @@ } private static final class PointerOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { - mem.putAddress(offset, Util.int64Value(value)); + if (value instanceof Pointer) { + mem.putAddress(offset, ((Pointer) value).address); + } else { + mem.putAddress(offset, Util.int64Value(value)); + } } public final PyObject get(Memory mem, long offset) { - return Py.newLong(mem.getAddress(offset)); + DirectMemory dm = new NativeMemory(mem.getAddress(offset)); + return new Pointer(dm.getAddress(), dm); } } private static final class StringOp extends MemoryOp { Added: branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/NullMemory.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -0,0 +1,35 @@ + + +package org.python.modules.jffi; + +/** + * An implementation of MemoryIO that throws an exception on any access. + */ +public class NullMemory extends InvalidMemory implements DirectMemory { + static final NullMemory INSTANCE = new NullMemory(); + public NullMemory() { + super("NULL pointer access"); + } + + public long getAddress() { + return 0L; + } + + public boolean isNull() { + return true; + } + public final boolean isDirect() { + return true; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof DirectMemory && ((DirectMemory) obj).getAddress() == 0; + } + + @Override + public int hashCode() { + return 0; + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -14,15 +14,35 @@ public final long address; final Memory memory; + final MemoryOp componentMemoryOp; public Pointer(PyType type, long address, Memory memory) { super(type); this.address = address; this.memory = memory; + this.componentMemoryOp = MemoryOp.INVALID; } public Pointer(long address, Memory memory) { this.address = address; this.memory = memory; + this.componentMemoryOp = MemoryOp.INVALID; } + + Pointer(DirectMemory memory, MemoryOp componentMemoryOp) { + this(TYPE, memory, componentMemoryOp); + } + + Pointer(PyType subtype, DirectMemory memory, MemoryOp componentMemoryOp) { + super(subtype); + this.address = memory.getAddress(); + this.memory = memory; + this.componentMemoryOp = componentMemoryOp; + } + + @ExposedGet(name="contents") + public PyObject contents() { + return componentMemoryOp.get(memory, 0); + } + } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -7,21 +7,14 @@ import org.python.core.PyObject; import org.python.core.PyObject.ConversionException; import org.python.core.PyType; -import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; -import org.python.expose.ExposedSet; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.ScalarCData", base = PyObject.class) -public class ScalarCData extends PyObject { +@ExposedType(name = "jffi.ScalarCData", base = CData.class) +public class ScalarCData extends CData { public static final PyType TYPE = PyType.fromClass(ScalarCData.class); - final Type.Builtin type; - private PyObject value; - private Memory memory; - - @ExposedNew public static PyObject ScalarCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { @@ -41,31 +34,9 @@ } ScalarCData(PyType pyType, Type.Builtin type) { - super(pyType); - this.type = type; - this.memory = null; - } + super(pyType, type, type.getMemoryOp()); + } - @ExposedGet(name = "value") - public PyObject getValue() { - // If native memory has been allocated, read the value from there - if (memory != null) { - return type.getMemoryOp().get(memory, 0); - } - - return value; - } - - - @ExposedSet(name = "value") - public void setValue(PyObject value) { - this.value = value; - // If native memory has been allocated, sync the value to memory - if (memory != null) { - type.getMemoryOp().put(memory, 0, value); - } - } - @Override public int asInt() { return getValue().asInt(); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Type.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 04:19:39 UTC (rev 6719) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Type.java 2009-08-26 05:25:19 UTC (rev 6720) @@ -1,20 +1,24 @@ package org.python.modules.jffi; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; +import org.python.core.PyObjectDerived; import org.python.core.PyType; import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.Type", base = PyObject.class) +@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) public class Type extends PyObject { public static final PyType TYPE = PyType.fromClass(Type.class); static { TYPE.fastGetDict().__setitem__("Array", Array.TYPE); + TYPE.fastGetDict().__setitem__("Pointer", Pointer.TYPE); } public static final Type VOID = primitive(NativeType.VOID); public static final Type SINT8 = primitive(NativeType.BYTE); @@ -55,7 +59,6 @@ this.memoryOp = memoryOp; } - public NativeType getNativeType() { return nativeType; } @@ -123,6 +126,104 @@ return length; } + @Override + public final String toString() { + return String.format("<jffi.Type.Array length=%d>", length); + } + } + @ExposedType(name = "jffi.Type.Pointer", base = Type.class) + final static class Pointer extends Type { + public static final PyType TYPE = PyType.fromClass(Pointer.class); + private static final ConcurrentMap<PyObject, Pointer> typeCache + = new ConcurrentHashMap<PyObject, Pointer>(); + + final Type componentType; + final PyType pyComponentType; + final MemoryOp componentMemoryOp; + + Pointer(PyType subtype, Type componentType, PyType pyComponentType) { + super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + this.componentType = componentType; + this.pyComponentType = pyComponentType; + if (pyComponentType.isSubType(ScalarCData.TYPE)) { + this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); + } else { + throw Py.TypeError("pointer only supported for scalar types"); + } + + } + + @ExposedNew + public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + Pointer p = typeCache.get(args[0]); + if (p != null) { + return p; + } + + if (args.length < 1) { + throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); + } + + if (!(args[0] instanceof Type)) { + throw Py.TypeError("expected jffi.Type"); + } + + if (args.length > 1 && !(args[1] instanceof PyType)) { + throw Py.TypeError("expected type"); + } + p = new Pointer(subtype, (Type) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); + typeCache.put(args[0], p); + + return p; + } + + @Override + public final String toString() { + return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); + } + + @Override + public PyObject __call__(PyObject value) { + if (value == Py.None) { + + return new org.python.modules.jffi.Pointer(new NullMemory(), componentMemoryOp); + + } else if (value.getType().isSubType(pyComponentType) && value instanceof CData) { + + return new org.python.modules.jffi.Pointer((DirectMemory) ((CData) value).getContentMemory(), componentMemoryOp); + + } else { + throw Py.TypeError("expected " + pyComponentType.getName() + " instead of " + value.getType().getName()); + } + } + + private static final class ScalarOp extends MemoryOp { + private final MemoryOp op; + private final PyType type; + + public ScalarOp(MemoryOp op, PyType type) { + this.op = op; + this.type = type; + } + + public final void put(Memory mem, long offset, PyObject value) { + op.put(mem, offset, value); + } + + public final PyObject get(Memory mem, long offset) { + PyObject result = type.__call__(op.get(mem, offset)); + // + // Point the CData to the backing memory so all value gets/sets + // update the same memory this pointer points to + // + if (result instanceof CData) { + ((CData) result).setContentMemory(mem); + } + return result; + } + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-26 10:09:07
|
Revision: 6722 http://jython.svn.sourceforge.net/jython/?rev=6722&view=rev Author: wmeissner Date: 2009-08-26 10:08:56 +0000 (Wed, 26 Aug 2009) Log Message: ----------- Fixup CType exposure Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/src/org/python/modules/jffi/CType.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-26 07:18:30 UTC (rev 6721) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-26 10:08:56 UTC (rev 6722) @@ -53,14 +53,14 @@ org/python/modules/_functools/PyPartial.class org/python/modules/_hashlib$Hash.class org/python/modules/jffi/CData.class +org/python/modules/jffi/CType.class +org/python/modules/jffi/CType$Array.class +org/python/modules/jffi/CType$Pointer.class org/python/modules/jffi/DynamicLibrary.class org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class org/python/modules/jffi/Pointer.class org/python/modules/jffi/ScalarCData.class -org/python/modules/jffi/Type.class -org/python/modules/jffi/Type$Array.class -org/python/modules/jffi/Type$Pointer.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-26 07:18:30 UTC (rev 6721) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-26 10:08:56 UTC (rev 6722) @@ -6,14 +6,13 @@ import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; -import org.python.core.PyObjectDerived; import org.python.core.PyType; import org.python.expose.ExposeAsSuperclass; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.Type", base = PyObjectDerived.class) +@ExposedType(name = "jffi.Type", base = PyObject.class) public class CType extends PyObject { public static final PyType TYPE = PyType.fromClass(CType.class); static { @@ -92,16 +91,30 @@ } } + private static CType typeOf(PyObject obj) { + if (obj instanceof CType) { + return (CType) obj; + } + + PyObject jffi_type = obj.__getattr__("_jffi_type"); + if (!(jffi_type instanceof CType)) { + throw Py.TypeError("invalid _jffi_type"); + } + return (CType) jffi_type; + } + @ExposedType(name = "jffi.Type.Array", base = CType.class) static final class Array extends CType { public static final PyType TYPE = PyType.fromClass(Array.class); final CType componentType; - + final PyObject pyComponentType; + @ExposedGet public final int length; - public Array(CType componentType, int length) { + public Array(PyObject pyComponentType, CType componentType, int length) { super(NativeType.ARRAY, new com.kenai.jffi.Array(componentType.jffiType, length), null); + this.pyComponentType = pyComponentType; this.componentType = componentType; this.length = length; } @@ -114,11 +127,7 @@ throw Py.TypeError(String.format("__init__() takes exactly 2 arguments (%d given)", args.length)); } - if (!(args[0] instanceof CType)) { - throw Py.TypeError("expected jffi.Type"); - } - - return new Array((CType) args[0], args[1].asInt()); + return new Array(args[0], typeOf(args[0]), args[1].asInt()); } @Override @@ -128,7 +137,7 @@ @Override public final String toString() { - return String.format("<jffi.Type.Array length=%d>", length); + return String.format("<ctypes.Array elem_type=%s length=%d>", pyComponentType.toString(), length); } } @@ -142,10 +151,11 @@ final PyType pyComponentType; final MemoryOp componentMemoryOp; - Pointer(PyType subtype, CType componentType, PyType pyComponentType) { + Pointer(PyType subtype, PyType pyComponentType, CType componentType) { super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + this.pyComponentType = pyComponentType; this.componentType = componentType; - this.pyComponentType = pyComponentType; + if (pyComponentType.isSubType(ScalarCData.TYPE)) { this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); } else { @@ -163,18 +173,15 @@ return p; } - if (args.length < 1) { + if (args.length != 1) { throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); } - if (!(args[0] instanceof CType)) { - throw Py.TypeError("expected jffi.Type"); + if (!(args[0] instanceof PyType)) { + throw Py.TypeError("expected ctypes class"); } - if (args.length > 1 && !(args[1] instanceof PyType)) { - throw Py.TypeError("expected type"); - } - p = new Pointer(subtype, (CType) args[0], args.length > 1 ? (PyType) args[1] : Py.None.getType()); + p = new Pointer(subtype, (PyType) args[0], typeOf(args[0])); typeCache.put(args[0], p); return p; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-31 01:13:45
|
Revision: 6731 http://jython.svn.sourceforge.net/jython/?rev=6731&view=rev Author: wmeissner Date: 2009-08-30 23:31:13 +0000 (Sun, 30 Aug 2009) Log Message: ----------- Fix some pointer and unsigned int parameter handling Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/Util.java Property Changed: ---------------- branches/ctypes-jffi/Lib/ctypes/ Property changes on: branches/ctypes-jffi/Lib/ctypes ___________________________________________________________________ Added: svn:ignore + *.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-30 22:17:24 UTC (rev 6730) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-30 23:31:13 UTC (rev 6731) @@ -37,7 +37,8 @@ return cdata.pointer() def POINTER(type): - return jffi.Type.Pointer(type._jffi_type, type) +# return jffi.Type.Pointer(type) + return c_void_p class c_byte(_ScalarCData): _jffi_type = jffi.Type.BYTE Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-30 22:17:24 UTC (rev 6730) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-30 23:31:13 UTC (rev 6731) @@ -372,7 +372,7 @@ public static final ParameterMarshaller INSTANCE = new Unsigned32Marshaller(); public void marshal(HeapInvocationBuffer buffer, PyObject arg) { - buffer.putInt((int) Util.int32Value(arg)); + buffer.putInt((int) Util.uint32Value(arg)); } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Util.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-08-30 22:17:24 UTC (rev 6730) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-08-30 23:31:13 UTC (rev 6731) @@ -67,8 +67,14 @@ return parameter.asInt(); } - public static final int uint32Value(PyObject parameter) { - return parameter.asInt(); + public static final int uint32Value(PyObject value) { + if (value instanceof PyInteger) { + return value.asInt(); + } else if (value instanceof PyLong) { + return (int) ((PyLong) value).asLong(0); + } else { + return (int) __long__value(value); + } } public static final long int64Value(PyObject value) { @@ -82,7 +88,13 @@ } public static final long uint64Value(PyObject value) { - return int64Value(value); + if (value instanceof PyLong) { + return ((PyLong) value).getValue().longValue(); + } else if (value instanceof PyInteger) { + return value.asInt(); + } else { + return __long__value(value); + } } public static final float floatValue(PyObject parameter) { @@ -93,6 +105,16 @@ return parameter.asDouble(); } + private static final long __long__value(PyObject value) { + PyObject l = value.__long__(); + if (l instanceof PyLong) { + return ((PyLong) l).getValue().longValue(); + } else if (l instanceof PyInteger) { + return value.asInt(); + } + throw Py.TypeError("invalid __long__() result"); + } + public static final void checkBounds(long size, long off, long len) { if ((off | len | (off + len) | (size - (off + len))) < 0) { throw Py.IndexError("Memory access offset=" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-31 08:54:10
|
Revision: 6732 http://jython.svn.sourceforge.net/jython/?rev=6732&view=rev Author: wmeissner Date: 2009-08-31 07:40:56 +0000 (Mon, 31 Aug 2009) Log Message: ----------- Start implementing POINTER() Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-30 23:31:13 UTC (rev 6731) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-31 07:40:56 UTC (rev 6732) @@ -36,10 +36,27 @@ def pointer(cdata): return cdata.pointer() -def POINTER(type): -# return jffi.Type.Pointer(type) - return c_void_p +_pointer_type_cache = {} +def POINTER(ctype): + # If a pointer class for the C type has been created, re-use it + if _pointer_type_cache.has_key(ctype): + return _pointer_type_cache[ctype] + # Create a new class for this particular C type + dict = { '_jffi_type': jffi.Type.Pointer(ctype) } + # 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 + + ptype = type("LP_%s" % (ctype.__name__,), (jffi.Pointer,), dict) + _pointer_type_cache[ctype] = ptype + return ptype + class c_byte(_ScalarCData): _jffi_type = jffi.Type.BYTE Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-30 23:31:13 UTC (rev 6731) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-31 07:40:56 UTC (rev 6732) @@ -1,9 +1,13 @@ 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.Pointer", base = PyObject.class) @@ -40,9 +44,35 @@ this.componentMemoryOp = componentMemoryOp; } + @ExposedNew + public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + + if (!(jffi_type instanceof CType.Pointer)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); + } + + CType.Pointer type = (CType.Pointer) jffi_type; + + if (args.length == 0) { + return new Pointer(subtype, NullMemory.INSTANCE, type.componentMemoryOp); + } + DirectMemory contents = AllocatedNativeMemory.allocate(type.componentType.size(), false); + type.componentMemoryOp.put(contents, 0, args[0]); + + return new Pointer(subtype, contents, type.componentMemoryOp); + } + @ExposedGet(name="contents") public PyObject contents() { return componentMemoryOp.get(memory, 0); } + @ExposedSet(name="contents") + public void contents(PyObject value) { + componentMemoryOp.put(memory, 0, value); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-08-31 14:38:33
|
Revision: 6733 http://jython.svn.sourceforge.net/jython/?rev=6733&view=rev Author: wmeissner Date: 2009-08-31 14:38:24 +0000 (Mon, 31 Aug 2009) Log Message: ----------- Rework Pointer and CData a lot to make PointerCData (and hopefully ArrayCData and StructCData) easier to implement Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/CType.java branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java branches/ctypes-jffi/src/org/python/modules/jffi/Function.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/CoreExposed.includes 2009-08-31 14:38:24 UTC (rev 6733) @@ -59,7 +59,7 @@ org/python/modules/jffi/DynamicLibrary.class org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class -org/python/modules/jffi/Pointer.class +org/python/modules/jffi/PointerCData.class org/python/modules/jffi/ScalarCData.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-08-31 14:38:24 UTC (rev 6733) @@ -53,7 +53,7 @@ name = mod.__name__ dict["__module__"] = name - ptype = type("LP_%s" % (ctype.__name__,), (jffi.Pointer,), dict) + ptype = type("LP_%s" % (ctype.__name__,), (jffi.PointerCData,), dict) _pointer_type_cache[ctype] = ptype return ptype Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -4,9 +4,7 @@ import org.python.core.Py; import org.python.core.PyObject; import org.python.core.PyType; -import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; -import org.python.expose.ExposedSet; import org.python.expose.ExposedType; @ExposedType(name = "jffi.CData", base = PyObject.class) @@ -16,65 +14,55 @@ final MemoryOp memoryOp; final CType type; - private Memory contentMemory; - private PyObject value; + private DirectMemory referenceMemory; CData(PyType subtype, CType type, MemoryOp memoryOp) { super(subtype); this.type = type; this.memoryOp = memoryOp; - this.value = Py.None; - this.contentMemory = null; + this.referenceMemory = null; } - - @ExposedGet(name = "value") - public PyObject getValue() { - // If native memory has been allocated, read the value from there - if (contentMemory != null) { - return memoryOp.get(contentMemory, 0); - } - - return value; - } - - - @ExposedSet(name = "value") - public void setValue(PyObject value) { - this.value = value; - // If native memory has been allocated, sync the value to memory - if (contentMemory != null) { - memoryOp.put(contentMemory, 0, value); - } - } - + @ExposedMethod(names= { "byref", "pointer" }) public PyObject byref() { - return new Pointer((DirectMemory) getContentMemory(), memoryOp); + return new PointerCData(type, getReferenceMemory(), memoryOp); } - boolean hasValueMemory() { - return contentMemory != null; + final boolean hasReferenceMemory() { + return referenceMemory != null; } - void setContentMemory(Memory memory) { + final void setReferenceMemory(Memory memory) { if (!(memory instanceof DirectMemory)) { throw Py.TypeError("invalid memory"); } - this.contentMemory = memory; + this.referenceMemory = (DirectMemory) memory; } - Memory getContentMemory() { - if (contentMemory != null) { - return contentMemory; + /** + * Returns the memory used when creating a reference to this instance. + * e.g. via byref(obj) + * + * @return The reference memory for this object + */ + public final DirectMemory getReferenceMemory() { + if (referenceMemory != null) { + return referenceMemory; } - return allocateDirect(); + return allocateReferenceMemory(); } - private DirectMemory allocateDirect() { + protected DirectMemory allocateReferenceMemory() { DirectMemory m = AllocatedNativeMemory.allocate(type.size(), false); - memoryOp.put(m, 0, value); - contentMemory = m; + initReferenceMemory(m); + this.referenceMemory = m; return m; } + + public Memory getContentMemory() { + return getReferenceMemory(); + } + + protected abstract void initReferenceMemory(Memory m); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -91,7 +91,7 @@ } } - private static CType typeOf(PyObject obj) { + static CType typeOf(PyObject obj) { if (obj instanceof CType) { return (CType) obj; } @@ -192,21 +192,6 @@ return String.format("<jffi.Type.Pointer component_type=%s>", componentType.toString()); } - @Override - public PyObject __call__(PyObject value) { - if (value == Py.None) { - - return new org.python.modules.jffi.Pointer(new NullMemory(), componentMemoryOp); - - } else if (value.getType().isSubType(pyComponentType) && value instanceof CData) { - - return new org.python.modules.jffi.Pointer((DirectMemory) ((CData) value).getContentMemory(), componentMemoryOp); - - } else { - throw Py.TypeError("expected " + pyComponentType.getName() + " instead of " + value.getType().getName()); - } - } - private static final class ScalarOp extends MemoryOp { private final MemoryOp op; private final PyType type; @@ -226,8 +211,8 @@ // Point the CData to the backing memory so all value gets/sets // update the same memory this pointer points to // - if (result instanceof CData) { - ((CData) result).setContentMemory(mem); + if (result instanceof ScalarCData) { + ((ScalarCData) result).setReferenceMemory(mem); } return result; } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -131,6 +131,8 @@ private static final ParameterMarshaller getMarshaller(CType type) { if (type instanceof CType.Builtin) { return getMarshaller(type.getNativeType()); + } else if (type instanceof CType.Pointer) { + return PointerMarshaller.INSTANCE; } else { throw Py.RuntimeError("Unsupported parameter type: " + type); } @@ -427,7 +429,7 @@ public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { if (parameter instanceof Pointer) { - buffer.putAddress(((Pointer) parameter).address); + buffer.putAddress(((Pointer) parameter).getAddress()); } else { throw Py.TypeError("expected pointer argument"); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -2,7 +2,6 @@ package org.python.modules.jffi; import com.kenai.jffi.Library; -import org.python.core.ClassDictInit; import org.python.core.Py; import org.python.core.PyObject; import org.python.core.PyType; @@ -43,7 +42,7 @@ @ExposedMethod public final PyObject find_symbol(PyObject name) { long address = findSymbol(name); - return new Symbol(this, name.asString(), address, new NativeMemory(address)); + return new Symbol(this, name.asString(), new NativeMemory(address)); } @ExposedMethod @@ -56,31 +55,49 @@ return new DataSymbol(this, name.asString(), findSymbol(name)); } - @ExposedType(name = "jffi.DynamicLibrary.Symbol", base = Pointer.class) - public static class Symbol extends Pointer { + @ExposedType(name = "jffi.DynamicLibrary.Symbol", base = PyObject.class) + public static class Symbol extends PyObject implements Pointer { public static final PyType TYPE = PyType.fromClass(Symbol.class); final DynamicLibrary library; + final DirectMemory memory; @ExposedGet + public final long address; + + @ExposedGet public final String name; - public Symbol(DynamicLibrary library, String name, long address, DirectMemory memory) { - super(address, memory); + public Symbol(DynamicLibrary library, String name, DirectMemory memory) { this.library = library; this.name = name; + this.memory = memory; + this.address = memory.getAddress(); } + + public final long getAddress() { + return address; + } + + public final DirectMemory getMemory() { + return memory; + } + + @Override + public boolean __nonzero__() { + return !getMemory().isNull(); + } } - public static class TextSymbol extends Symbol implements ExposeAsSuperclass { + public static final class TextSymbol extends Symbol implements ExposeAsSuperclass { public TextSymbol(DynamicLibrary lib, String name, long address) { - super(lib, name, address, new NativeMemory(address)); + super(lib, name, new NativeMemory(address)); } } - public static class DataSymbol extends Symbol implements ExposeAsSuperclass { + public static final class DataSymbol extends Symbol implements ExposeAsSuperclass { public DataSymbol(DynamicLibrary lib, String name, long address) { - super(lib, name, address, new NativeMemory(address)); + super(lib, name, new NativeMemory(address)); } } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Function.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -12,8 +12,8 @@ import org.python.expose.ExposedSet; import org.python.expose.ExposedType; -@ExposedType(name = "jffi.Function", base = Pointer.class) -public class Function extends Pointer { +@ExposedType(name = "jffi.Function", base = PyObject.class) +public class Function extends PyObject implements Pointer { public static final PyType TYPE = PyType.fromClass(Function.class); private final Pointer pointer; @@ -27,37 +27,37 @@ @ExposedGet public final String name; - + @ExposedGet + public final long address; + + @ExposedGet @ExposedSet public PyObject restype; - Function(PyType type, Pointer address, DirectMemory memory) { - super(type, address.address, memory); + Function(PyType type, Pointer address) { + super(type); + this.address = address.getAddress(); this.library = null; this.name = "<anonymous>"; this.pointer = address; } - Function(PyType type, Pointer address) { - this(type, address, new NativeMemory(address.address)); + Function(PyType type, DynamicLibrary.Symbol sym) { + super(type); + this.library = sym.library; + this.name = sym.name; + this.pointer = sym; + this.address = sym.getAddress(); } - Function(PyType type, DynamicLibrary library, String name, long address) { - super(type, address, new NativeMemory(address)); - this.library = library; - this.name = name; - this.pointer = null; - } - @ExposedNew public static PyObject Function_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { if (args[0] instanceof Pointer) { if (args[0] instanceof DynamicLibrary.Symbol) { - DynamicLibrary.Symbol sym = (DynamicLibrary.Symbol) args[0]; - return new Function(subtype, sym.library, sym.name, sym.address); + return new Function(subtype, (DynamicLibrary.Symbol) args[0]); } else { return new Function(subtype, (Pointer) args[0]); } @@ -66,6 +66,14 @@ } } + public long getAddress() { + return address; + } + + public DirectMemory getMemory() { + return pointer.getMemory(); + } + @Override public PyObject fastGetDict() { return dict; @@ -125,6 +133,8 @@ @ExposedSet(name = "_jffi_argtypes") public void setParameterTypes(PyObject parameterTypes) { + this.invoker = null; // invalidate old invoker + // Removing the parameter types defaults back to varargs if (parameterTypes == Py.None) { this.parameterTypes = null; @@ -144,10 +154,13 @@ paramTypes[i] = (CType) t; } - this.invoker = null; // invalidate old invoker this.parameterTypes = paramTypes; } + @Override + public boolean __nonzero__() { + return !getMemory().isNull(); + } private final Invoker getInvoker() { if (invoker != null) { Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -178,7 +178,7 @@ private static final class PointerOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { if (value instanceof Pointer) { - mem.putAddress(offset, ((Pointer) value).address); + mem.putAddress(offset, ((Pointer) value).getAddress()); } else { mem.putAddress(offset, Util.int64Value(value)); } @@ -186,7 +186,7 @@ public final PyObject get(Memory mem, long offset) { DirectMemory dm = new NativeMemory(mem.getAddress(offset)); - return new Pointer(dm.getAddress(), dm); + return new PointerCData(CType.POINTER, dm, INVALID); } } private static final class StringOp extends MemoryOp { Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Pointer.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -1,78 +1,7 @@ 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.Pointer", base = PyObject.class) -public class Pointer extends PyObject { - public static final PyType TYPE = PyType.fromClass(Pointer.class); - - @ExposedGet - public final long address; - - final Memory memory; - final MemoryOp componentMemoryOp; - - public Pointer(PyType type, long address, Memory memory) { - super(type); - this.address = address; - this.memory = memory; - this.componentMemoryOp = MemoryOp.INVALID; - } - - public Pointer(long address, Memory memory) { - this.address = address; - this.memory = memory; - this.componentMemoryOp = MemoryOp.INVALID; - } - - Pointer(DirectMemory memory, MemoryOp componentMemoryOp) { - this(TYPE, memory, componentMemoryOp); - } - - Pointer(PyType subtype, DirectMemory memory, MemoryOp componentMemoryOp) { - super(subtype); - this.address = memory.getAddress(); - this.memory = memory; - this.componentMemoryOp = componentMemoryOp; - } - - @ExposedNew - public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, - PyObject[] args, String[] keywords) { - - PyObject jffi_type = subtype.__getattr__("_jffi_type"); - - if (!(jffi_type instanceof CType.Pointer)) { - throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); - } - - CType.Pointer type = (CType.Pointer) jffi_type; - - if (args.length == 0) { - return new Pointer(subtype, NullMemory.INSTANCE, type.componentMemoryOp); - } - DirectMemory contents = AllocatedNativeMemory.allocate(type.componentType.size(), false); - type.componentMemoryOp.put(contents, 0, args[0]); - - return new Pointer(subtype, contents, type.componentMemoryOp); - } - - @ExposedGet(name="contents") - public PyObject contents() { - return componentMemoryOp.get(memory, 0); - } - - @ExposedSet(name="contents") - public void contents(PyObject value) { - componentMemoryOp.put(memory, 0, value); - } - +public interface Pointer { + long getAddress(); + DirectMemory getMemory(); } Added: branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -0,0 +1,84 @@ + +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.PointerCData", base = CData.class) +public class PointerCData extends CData 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, type.getMemoryOp()); + this.memory = memory; + this.componentMemoryOp = componentMemoryOp; + } + + PointerCData(CType type, DirectMemory memory, MemoryOp componentMemoryOp) { + this(TYPE, type, memory, componentMemoryOp); + } + + + @ExposedNew + public static PyObject PointerCData_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + + if (!(jffi_type instanceof CType.Pointer)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); + } + + CType.Pointer type = (CType.Pointer) jffi_type; + + if (args.length == 0) { + return new PointerCData(subtype, type, NullMemory.INSTANCE, type.componentMemoryOp); + } + PyObject value = args[0]; + if (value instanceof CData && value.getType().isSubType(type.pyComponentType)) { + + return new PointerCData(subtype, type, ((CData) value).getReferenceMemory(), type.componentMemoryOp); + + } else { + throw Py.TypeError("expected " + type.pyComponentType.getName() + " instead of " + value.getType().getName()); + } + } + + @ExposedGet(name="contents") + public PyObject getContents() { + return componentMemoryOp.get(getMemory(), 0); + } + + @ExposedSet(name="contents") + 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; + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -7,14 +7,18 @@ import org.python.core.PyObject; import org.python.core.PyObject.ConversionException; import org.python.core.PyType; +import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; +import org.python.expose.ExposedSet; import org.python.expose.ExposedType; @ExposedType(name = "jffi.ScalarCData", base = CData.class) public class ScalarCData extends CData { public static final PyType TYPE = PyType.fromClass(ScalarCData.class); + private PyObject value = Py.None; + @ExposedNew public static PyObject ScalarCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { @@ -35,8 +39,33 @@ ScalarCData(PyType pyType, CType.Builtin type) { super(pyType, type, type.getMemoryOp()); - } + } + protected final void initReferenceMemory(Memory m) { + memoryOp.put(m, 0, value); + } + + @ExposedGet(name = "value") + public PyObject getValue() { + // If native memory has been allocated, read the value from there + if (hasReferenceMemory()) { + return memoryOp.get(getReferenceMemory(), 0); + } + + return value; + } + + + @ExposedSet(name = "value") + public void setValue(PyObject value) { + this.value = value; + // If native memory has been allocated, sync the value to memory + if (hasReferenceMemory()) { + memoryOp.put(getReferenceMemory(), 0, value); + } + } + + @Override public int asInt() { return getValue().asInt(); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-08-31 07:40:56 UTC (rev 6732) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-08-31 14:38:24 UTC (rev 6733) @@ -19,8 +19,8 @@ dict.__setitem__("__name__", Py.newString("jffi")); dict.__setitem__("DynamicLibrary", DynamicLibrary.TYPE); dict.__setitem__("Type", CType.TYPE); - dict.__setitem__("Pointer", Pointer.TYPE); dict.__setitem__("Function", Function.TYPE); + dict.__setitem__("PointerCData", PointerCData.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); dict.__setitem__("FUNCFLAG_STDCALL", Py.newInteger(FUNCFLAG_STDCALL)); dict.__setitem__("FUNCFLAG_CDECL", Py.newInteger(FUNCFLAG_CDECL)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-02 07:20:45
|
Revision: 6743 http://jython.svn.sourceforge.net/jython/?rev=6743&view=rev Author: wmeissner Date: 2009-09-02 07:20:36 +0000 (Wed, 02 Sep 2009) Log Message: ----------- Implement structs with simple (non-bitfield) scalar members Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/CType.java branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/CoreExposed.includes 2009-09-02 07:20:36 UTC (rev 6743) @@ -60,7 +60,11 @@ org/python/modules/jffi/DynamicLibrary$Symbol.class org/python/modules/jffi/Function.class org/python/modules/jffi/PointerCData.class +org/python/modules/jffi/Structure.class org/python/modules/jffi/ScalarCData.class +org/python/modules/jffi/StructLayout.class +org/python/modules/jffi/StructLayout$Field.class +org/python/modules/jffi/StructLayout$ScalarField.class org/python/modules/_threading/Condition.class org/python/modules/_threading/Lock.class org/python/modules/_weakref/CallableProxyType.class Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-02 07:20:36 UTC (rev 6743) @@ -24,6 +24,70 @@ def __len__(self): return self._jffi_type.length +class _StructLayoutBuilder(object): + def __init__(self, union = False): + self.size = 0 + self.offset = 0 + self.fields = [] + self.union = union + + def align(self, offset, align): + return align + ((offset - 1) & ~(align - 1)); + + def add_fields(self, fields): + for f in fields: + self.add_field(f) + return self + + def add_field(self, f): + if not issubclass(f[1], _ScalarCData): + raise RuntimeError("non-scalar fields not supported") + + if len(f) != 2: + raise RuntimeError("structs with bitfields not supported") + + self.offset = self.align(self.offset, alignment(f[1])) + self.fields.append(jffi.StructLayout.ScalarField(f[0], f[1], self.offset)) + if not self.union: + self.offset += sizeof(f[1]) + self.size = max(self.offset, sizeof(f[1])) + + return self + + def build(self): + return jffi.StructLayout(fields = self.fields, union = self.union) + +class _StructMetaClass(type): + def __new__(cls, name, bases, dict): + try: + layout = dict['_jffi_type'] = _StructLayoutBuilder().add_fields(dict['_fields_']).build() + # make all fields accessible via .foo + for f in dict['_fields_']: + dict[f[0]] = layout[f[0]] + except: + pass + + return type.__new__(cls, name, bases, dict) + +class _UnionMetaClass(type): + def __new__(cls, name, bases, dict): + try: + layout = dict['_jffi_type'] = _StructLayoutBuilder().add_fields(dict['_fields_'], union = True).build() + # make all fields accessible via .foo + for f in dict['_fields_']: + dict[f[0]] = layout[f[0]] + except: + pass + + + return type.__new__(cls, name, bases, dict) + +class Structure(jffi.Structure): + __metaclass__ = _StructMetaClass + +class Union(jffi.Structure): + __metaclass__ = _UnionMetaClass + def sizeof(type): return type._jffi_type.size @@ -34,7 +98,7 @@ return cdata.byref() def pointer(cdata): - return cdata.pointer() + return cdata.pointer(POINTER(cdata.__class__)) _pointer_type_cache = {} def POINTER(ctype): @@ -170,14 +234,3 @@ return self._dlltype(name) cdll = LibraryLoader(CDLL) - -# -#class _StructMetaClass(type): -# def __new__(cls, name, bases, dict): -# for attr in dict: -# if attr == '_fields_': -# print "%s has attr %s" % (name, attr) -# return type.__new__(cls, name, bases, dict) -# -#class Structure: -# __metaclass__ = _StructMetaClass Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -23,11 +23,20 @@ this.referenceMemory = null; } - @ExposedMethod(names= { "byref", "pointer" }) + @ExposedMethod(names= { "byref" }) public PyObject byref() { - return new PointerCData(type, getReferenceMemory(), memoryOp); + return new PointerCData(PointerCData.TYPE, type, getReferenceMemory(), memoryOp); } + @ExposedMethod(names= { "pointer" }) + public PyObject pointer(PyObject pytype) { + if (!(pytype instanceof PyType)) { + throw Py.TypeError("expected type"); + } + + return new PointerCData((PyType) pytype, type, getReferenceMemory(), memoryOp); + } + final boolean hasReferenceMemory() { return referenceMemory != null; } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -152,12 +152,14 @@ final MemoryOp componentMemoryOp; Pointer(PyType subtype, PyType pyComponentType, CType componentType) { - super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, MemoryOp.POINTER); + super(NativeType.POINTER, com.kenai.jffi.Type.POINTER, new MemoryOp.PointerOp(subtype, CType.POINTER)); this.pyComponentType = pyComponentType; this.componentType = componentType; if (pyComponentType.isSubType(ScalarCData.TYPE)) { - this.componentMemoryOp = new ScalarOp(MemoryOp.getMemoryOp(componentType.getNativeType()), pyComponentType); + this.componentMemoryOp = new ScalarOp(componentType.getMemoryOp(), pyComponentType); + } else if (pyComponentType.isSubType(Structure.TYPE)) { + this.componentMemoryOp = new MemoryOp.StructOp(pyComponentType); } else { throw Py.TypeError("pointer only supported for scalar types"); } @@ -168,15 +170,15 @@ public static PyObject Pointer_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { + if (args.length != 1) { + throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); + } + Pointer p = typeCache.get(args[0]); if (p != null) { return p; } - if (args.length != 1) { - throw Py.TypeError(String.format("__init__() takes exactly 1 argument (%d given)", args.length)); - } - if (!(args[0] instanceof PyType)) { throw Py.TypeError("expected ctypes class"); } @@ -217,5 +219,7 @@ return result; } } + + } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -430,6 +430,8 @@ public void marshal(HeapInvocationBuffer buffer, PyObject parameter) { if (parameter instanceof Pointer) { buffer.putAddress(((Pointer) parameter).getAddress()); + } else if (parameter == Py.None) { + buffer.putAddress(0); } else { throw Py.TypeError("expected pointer argument"); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -3,6 +3,7 @@ import org.python.core.Py; import org.python.core.PyObject; +import org.python.core.PyType; /** * Defines memory operations for a primitive type @@ -20,7 +21,7 @@ public static final MemoryOp UINT64 = new Unsigned64(); public static final MemoryOp FLOAT = new Float32(); public static final MemoryOp DOUBLE = new Float64(); - public static final MemoryOp POINTER = new PointerOp(); + public static final MemoryOp POINTER = new PointerOp(PointerCData.TYPE, CType.POINTER); public static final MemoryOp STRING = new StringOp(); public static final MemoryOp getMemoryOp(NativeType type) { @@ -175,7 +176,15 @@ return Py.newFloat(mem.getDouble(offset)); } } - private static final class PointerOp extends MemoryOp { + static final class PointerOp extends MemoryOp { + private final PyType pytype; + private final CType ctype; + + public PointerOp(PyType pytype, CType ctype) { + this.pytype = pytype; + this.ctype = ctype; + } + public final void put(Memory mem, long offset, PyObject value) { if (value instanceof Pointer) { mem.putAddress(offset, ((Pointer) value).getAddress()); @@ -186,9 +195,10 @@ public final PyObject get(Memory mem, long offset) { DirectMemory dm = new NativeMemory(mem.getAddress(offset)); - return new PointerCData(CType.POINTER, dm, INVALID); + return new PointerCData(pytype, ctype, dm, INVALID); } } + private static final class StringOp extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { throw Py.NotImplementedError("Cannot set String"); @@ -198,4 +208,32 @@ throw Py.NotImplementedError("Cannot get String"); } } + + static final class StructOp extends MemoryOp { + + private final PyType type; + private final StructLayout layout; + + public StructOp(PyType type) { + this.type = type; + PyObject l = type.__getattr__("_jffi_type"); + if (!(l instanceof StructLayout)) { + throw Py.TypeError("invalid _jffi_type for " + type.fastGetName() + "; should be instance of jffi.StructLayout"); + } + this.layout = (StructLayout) l; + } + + public StructOp(PyType type, StructLayout layout) { + this.type = type; + this.layout = layout; + } + + public final void put(Memory mem, long offset, PyObject value) { + throw Py.NotImplementedError("not implemented"); + } + + public final PyObject get(Memory mem, long offset) { + return new Structure(type, layout, mem.slice(offset)); + } + } } Added: branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -0,0 +1,160 @@ + +package org.python.modules.jffi; + +import java.util.HashMap; +import java.util.Map; +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyList; +import org.python.core.PyNewWrapper; +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.StructLayout", base = CType.class) +public class StructLayout extends CType { + public static final PyType TYPE = PyType.fromClass(StructLayout.class); + static { + TYPE.fastGetDict().__setitem__("Field", Field.TYPE); + TYPE.fastGetDict().__setitem__("ScalarField", ScalarField.TYPE); + } + + private final Map<PyObject, Field> fieldMap; + + StructLayout(Field[] fields, com.kenai.jffi.Type struct, MemoryOp op) { + super(NativeType.STRUCT, struct, op); + Map<PyObject, Field> m = new HashMap<PyObject, Field>(fields.length); + for (Field f : fields) { + m.put(f.name, f); + } + this.fieldMap = m; + } + + @ExposedType(name = "jffi.StructLayout.Field", base = PyObject.class) + public static class Field extends PyObject { + public static final PyType TYPE = PyType.fromClass(Field.class); + @ExposedGet + final CType ctype; + + @ExposedGet + final int offset; + + final PyObject name; + + final MemoryOp op; + + Field(PyObject name, CType ctype, int offset, MemoryOp op) { + this.name = name; + this.ctype = ctype; + this.offset = offset; + this.op = op; + } + + Field(PyObject name, CType ctype, int offset) { + this(name, ctype, offset, ctype.getMemoryOp()); + } + + private static org.python.modules.jffi.Pointer asPointer(PyObject obj) { + if (!(obj instanceof org.python.modules.jffi.Pointer)) { + throw Py.TypeError("expected pointer"); + } + + return (org.python.modules.jffi.Pointer) obj; + } + + @Override + public PyObject __get__(PyObject obj, PyObject type) { + return Field___get__(obj, type); + } + + @Override + public void __set__(PyObject obj, PyObject value) { + Field___set__(obj, value); + } + + @ExposedMethod + public PyObject Field___get__(PyObject obj, PyObject type) { + return op.get(asPointer(obj).getMemory(), offset); + } + + @ExposedMethod + public void Field___set__(PyObject obj, PyObject value) { + op.put(asPointer(obj).getMemory(), offset, value); + } + + + @ExposedMethod(names={"get" }) + PyObject get(PyObject obj) { + return op.get(asPointer(obj).getMemory(), offset); + } + + @ExposedMethod(names={"set"}) + PyObject set(PyObject obj, PyObject value) { + + op.put(asPointer(obj).getMemory(), offset, value); + + return value; + } + } + + @ExposedNew + public static PyObject StructLayout_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + ArgParser ap = new ArgParser("__init__", args, keywords, new String[] { "fields", "union" }, 1); + + if (!(ap.getPyObject(0) instanceof PyList)) { + throw Py.TypeError("expected list of jffi.StructLayout.Field"); + } + + PyList pyFields = (PyList) ap.getPyObject(0); + com.kenai.jffi.Type[] fieldTypes = new com.kenai.jffi.Type[pyFields.size()]; + Field[] fields = new Field[pyFields.size()]; + + for (int i = 0; i < fields.length; ++i) { + PyObject pyField = pyFields.pyget(i); + if (!(pyField instanceof Field)) { + throw Py.TypeError(String.format("element %d of field list is not an instance of jffi.StructLayout.Field", i)); + } + Field f = (Field) pyField; + fields[i] = f; + fieldTypes[i] = f.ctype.jffiType; + } + + com.kenai.jffi.Type jffiType = ap.getPyObject(1, Py.False).__nonzero__() + ? new com.kenai.jffi.Union(fieldTypes) + : new com.kenai.jffi.Struct(fieldTypes); + + return new StructLayout(fields, jffiType, MemoryOp.INVALID); + } + + @ExposedType(name = "jffi.StructLayout.ScalarField", base = Field.class) + public static class ScalarField extends Field { + public static final PyType TYPE = PyType.fromClass(ScalarField.class); + + public ScalarField(PyObject name, CType ctype, int offset) { + super(name, ctype, offset); + } + + @ExposedNew + public static PyObject ScalarField_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("__init__", args, keywords, new String[] { "name", "type", "offset"}); + + return new ScalarField(ap.getPyObject(0), CType.typeOf(ap.getPyObject(1)), ap.getInt(2)); + } + } + + Field getField(PyObject name) { + return fieldMap.get(name); + } + + @Override + public PyObject __getitem__(PyObject key) { + StructLayout.Field f = getField(key); + return f != null ? f : Py.None; + } +} Added: branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -0,0 +1,71 @@ + +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.ExposedNew; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.Structure", base = CData.class) +public class Structure extends CData implements Pointer { + public static final PyType TYPE = PyType.fromClass(Structure.class); + + private final StructLayout layout; + + Structure(PyType pyType, StructLayout layout) { + this(pyType, layout, AllocatedNativeMemory.allocate(layout.size(), true)); + } + + Structure(PyType pyType, StructLayout layout, Memory m) { + super(pyType, layout, new MemoryOp.StructOp(pyType, layout)); + this.layout = layout; + setReferenceMemory(m); + } + + @ExposedNew + public static PyObject Structure_new(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + + PyObject layout = subtype.__getattr__("_jffi_type"); + if (!(layout instanceof StructLayout)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.fastGetName() + "; should be instance of jffi.StructLayout"); + } + + return new Structure(subtype, (StructLayout) layout); + } + + protected final void initReferenceMemory(Memory m) { + throw Py.RuntimeError("reference memory already initialized"); + } + + StructLayout.Field getField(PyObject key) { + StructLayout.Field f = layout.getField(key); + if (f == null) { + throw Py.NameError(String.format("struct %s has no field '%s'", getType().fastGetName(), key.toString())); + } + return f; + } + + @Override + public PyObject __getitem__(PyObject key) { + StructLayout.Field f = getField(key); + return f.op.get(getReferenceMemory(), f.offset); + } + + @Override + public void __setitem__(PyObject key, PyObject value) { + StructLayout.Field f = getField(key); + f.op.put(getReferenceMemory(), f.offset, value); + } + + public long getAddress() { + return getMemory().getAddress(); + } + + public DirectMemory getMemory() { + return getReferenceMemory(); + } + +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-01 14:27:33 UTC (rev 6742) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-02 07:20:36 UTC (rev 6743) @@ -22,6 +22,8 @@ dict.__setitem__("Function", Function.TYPE); dict.__setitem__("PointerCData", PointerCData.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); + dict.__setitem__("Structure", Structure.TYPE); + dict.__setitem__("StructLayout", StructLayout.TYPE); dict.__setitem__("FUNCFLAG_STDCALL", Py.newInteger(FUNCFLAG_STDCALL)); dict.__setitem__("FUNCFLAG_CDECL", Py.newInteger(FUNCFLAG_CDECL)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-03 15:02:48
|
Revision: 6744 http://jython.svn.sourceforge.net/jython/?rev=6744&view=rev Author: wmeissner Date: 2009-09-03 15:02:40 +0000 (Thu, 03 Sep 2009) Log Message: ----------- Use a slightly more lightweight ByReference instance for byref() parameters. Add CData#getMemoryOp() instead of storing the memoryOp in CData Modified Paths: -------------- branches/ctypes-jffi/CoreExposed.includes branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java Added Paths: ----------- branches/ctypes-jffi/src/org/python/modules/jffi/ByReference.java Modified: branches/ctypes-jffi/CoreExposed.includes =================================================================== --- branches/ctypes-jffi/CoreExposed.includes 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/CoreExposed.includes 2009-09-03 15:02:40 UTC (rev 6744) @@ -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/ByReference.class org/python/modules/jffi/CData.class org/python/modules/jffi/CType.class org/python/modules/jffi/CType$Array.class Added: branches/ctypes-jffi/src/org/python/modules/jffi/ByReference.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ByReference.java (rev 0) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ByReference.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -0,0 +1,26 @@ + +package org.python.modules.jffi; + +import org.python.core.PyObject; +import org.python.core.PyType; +import org.python.expose.ExposedType; + +@ExposedType(name = "jffi.ByReference", base = PyObject.class) +public final class ByReference extends PyObject implements Pointer { + public static final PyType TYPE = PyType.fromClass(ByReference.class); + + private final DirectMemory memory; + + ByReference(CType componentType, DirectMemory memory) { + super(TYPE); + this.memory = memory; + } + + public long getAddress() { + return getMemory().getAddress(); + } + + public final DirectMemory getMemory() { + return memory; + } +} Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -10,22 +10,26 @@ @ExposedType(name = "jffi.CData", base = PyObject.class) public abstract class CData extends PyObject { public static final PyType TYPE = PyType.fromClass(CData.class); + + private final CType ctype; - final MemoryOp memoryOp; - final CType type; - private DirectMemory referenceMemory; - CData(PyType subtype, CType type, MemoryOp memoryOp) { + CData(PyType subtype, CType type) { super(subtype); - this.type = type; - this.memoryOp = memoryOp; + this.ctype = type; this.referenceMemory = null; } - + + /** + * Wraps up this object in a pointer that can be passed to native code. + * The byref() return value cannot be used as anything other than a parameter. + * + * @return A ByReference instance pointing to this object's native memory. + */ @ExposedMethod(names= { "byref" }) public PyObject byref() { - return new PointerCData(PointerCData.TYPE, type, getReferenceMemory(), memoryOp); + return new ByReference(ctype, getReferenceMemory()); } @ExposedMethod(names= { "pointer" }) @@ -34,9 +38,17 @@ throw Py.TypeError("expected type"); } - return new PointerCData((PyType) pytype, type, getReferenceMemory(), memoryOp); + return new PointerCData((PyType) pytype, CType.typeOf(pytype), getReferenceMemory(), getMemoryOp()); } + final CType getCType() { + return ctype; + } + + MemoryOp getMemoryOp() { + return getCType().getMemoryOp(); + } + final boolean hasReferenceMemory() { return referenceMemory != null; } @@ -63,7 +75,7 @@ } protected DirectMemory allocateReferenceMemory() { - DirectMemory m = AllocatedNativeMemory.allocate(type.size(), false); + DirectMemory m = AllocatedNativeMemory.allocate(getCType().size(), false); initReferenceMemory(m); this.referenceMemory = m; return m; Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -188,8 +188,10 @@ public final void put(Memory mem, long offset, PyObject value) { if (value instanceof Pointer) { mem.putAddress(offset, ((Pointer) value).getAddress()); + } else if (value == Py.None) { + mem.putAddress(offset, 0); } else { - mem.putAddress(offset, Util.int64Value(value)); + throw Py.RuntimeError("invalid pointer"); } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -18,16 +18,11 @@ final MemoryOp componentMemoryOp; PointerCData(PyType subtype, CType type, DirectMemory memory, MemoryOp componentMemoryOp) { - super(subtype, type, type.getMemoryOp()); + super(subtype, type); this.memory = memory; this.componentMemoryOp = componentMemoryOp; } - - PointerCData(CType type, DirectMemory memory, MemoryOp componentMemoryOp) { - this(TYPE, type, memory, componentMemoryOp); - } - - + @ExposedNew public static PyObject PointerCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { @@ -38,18 +33,20 @@ throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); } - CType.Pointer type = (CType.Pointer) jffi_type; + CType.Pointer pointerType = (CType.Pointer) jffi_type; + // No args == create NULL pointer if (args.length == 0) { - return new PointerCData(subtype, type, NullMemory.INSTANCE, type.componentMemoryOp); + return new PointerCData(subtype, pointerType, NullMemory.INSTANCE, pointerType.componentMemoryOp); } + PyObject value = args[0]; - if (value instanceof CData && value.getType().isSubType(type.pyComponentType)) { + if (value instanceof CData && value.getType().isSubType(pointerType.pyComponentType)) { - return new PointerCData(subtype, type, ((CData) value).getReferenceMemory(), type.componentMemoryOp); + return new PointerCData(subtype, pointerType, ((CData) value).getReferenceMemory(), pointerType.componentMemoryOp); } else { - throw Py.TypeError("expected " + type.pyComponentType.getName() + " instead of " + value.getType().getName()); + throw Py.TypeError("expected " + pointerType.pyComponentType.getName() + " instead of " + value.getType().getName()); } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -37,19 +37,19 @@ return cdata; } - ScalarCData(PyType pyType, CType.Builtin type) { - super(pyType, type, type.getMemoryOp()); + ScalarCData(PyType pytype, CType.Builtin ctype) { + super(pytype, ctype); } protected final void initReferenceMemory(Memory m) { - memoryOp.put(m, 0, value); + getMemoryOp().put(m, 0, value); } @ExposedGet(name = "value") public PyObject getValue() { // If native memory has been allocated, read the value from there if (hasReferenceMemory()) { - return memoryOp.get(getReferenceMemory(), 0); + return getMemoryOp().get(getReferenceMemory(), 0); } return value; @@ -61,7 +61,7 @@ this.value = value; // If native memory has been allocated, sync the value to memory if (hasReferenceMemory()) { - memoryOp.put(getReferenceMemory(), 0, value); + getMemoryOp().put(getReferenceMemory(), 0, value); } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-02 07:20:36 UTC (rev 6743) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-03 15:02:40 UTC (rev 6744) @@ -13,14 +13,16 @@ public static final PyType TYPE = PyType.fromClass(Structure.class); private final StructLayout layout; + private final MemoryOp memoryOp; Structure(PyType pyType, StructLayout layout) { this(pyType, layout, AllocatedNativeMemory.allocate(layout.size(), true)); } Structure(PyType pyType, StructLayout layout, Memory m) { - super(pyType, layout, new MemoryOp.StructOp(pyType, layout)); + super(pyType, layout); this.layout = layout; + this.memoryOp = new MemoryOp.StructOp(pyType, layout); setReferenceMemory(m); } @@ -40,6 +42,11 @@ throw Py.RuntimeError("reference memory already initialized"); } + @Override + MemoryOp getMemoryOp() { + return memoryOp; + } + StructLayout.Field getField(PyObject key) { StructLayout.Field f = layout.getField(key); if (f == null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-03 15:46:07
|
Revision: 6745 http://jython.svn.sourceforge.net/jython/?rev=6745&view=rev Author: wmeissner Date: 2009-09-03 15:45:59 +0000 (Thu, 03 Sep 2009) Log Message: ----------- Add _type_ attribute to basic ctypes classes, and add c_bool Modified Paths: -------------- 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/MemoryOp.java branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-03 15:02:40 UTC (rev 6744) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-03 15:45:59 UTC (rev 6745) @@ -1,5 +1,23 @@ import jffi +_TypeMap = { + 'b': jffi.Type.BYTE, + 'B': jffi.Type.UBYTE, + 'h': jffi.Type.SHORT, + 'H': jffi.Type.USHORT, + 'i': jffi.Type.INT, + 'I': jffi.Type.UINT, + 'l': jffi.Type.LONG, + 'L': jffi.Type.ULONG, + 'q': jffi.Type.LONGLONG, + 'Q': jffi.Type.ULONGLONG, + 'f': jffi.Type.FLOAT, + 'd': jffi.Type.DOUBLE, + '?': jffi.Type.BOOL, + 'z': jffi.Type.STRING, + 'P': jffi.Type.POINTER +} + class _CTypeMetaClass(type): def __new__(cls, name, bases, dict): @@ -89,7 +107,12 @@ __metaclass__ = _UnionMetaClass def sizeof(type): - return type._jffi_type.size + if isinstance(type, jffi.CData): + return type._jffi_type.size + elif hasattr(type, '_type_'): + return _TypeMap[type.__getattribute__('_type_')] + else: + raise TypeError("invalid ctype") def alignment(type): return type._jffi_type.alignment @@ -121,40 +144,56 @@ _pointer_type_cache[ctype] = ptype return ptype +class c_bool(_ScalarCData): + _type_ = "?" + _jffi_type = jffi.Type.BOOL + class c_byte(_ScalarCData): + _type_ = 'b' _jffi_type = jffi.Type.BYTE class c_ubyte(_ScalarCData): + _type_ = 'B' _jffi_type = jffi.Type.UBYTE class c_short(_ScalarCData): + _type_ = 'h' _jffi_type = jffi.Type.SHORT class c_ushort(_ScalarCData): + _type_ = 'H' _jffi_type = jffi.Type.USHORT class c_int(_ScalarCData): + _type_ = 'i' _jffi_type = jffi.Type.INT class c_uint(_ScalarCData): + _type_ = 'I' _jffi_type = jffi.Type.UINT class c_longlong(_ScalarCData): + _type_ = 'q' _jffi_type = jffi.Type.LONGLONG class c_ulonglong(_ScalarCData): + _type_ = 'Q' _jffi_type = jffi.Type.ULONGLONG class c_long(_ScalarCData): + _type_ = 'l' _jffi_type = jffi.Type.LONG class c_ulong(_ScalarCData): + _type_ = 'L' _jffi_type = jffi.Type.ULONG class c_float(_ScalarCData): + _type_ = 'f' _jffi_type = jffi.Type.FLOAT class c_double(_ScalarCData): + _type_ = 'd' _jffi_type = jffi.Type.DOUBLE c_int8 = c_byte @@ -170,9 +209,11 @@ c_ssize_t = c_long class c_char_p(_ScalarCData): + _type_ = 'z' _jffi_type = jffi.Type.STRING class c_void_p(_ScalarCData): + _type_ = 'P' _jffi_type = jffi.Type.POINTER class _Function(jffi.Function): Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-03 15:02:40 UTC (rev 6744) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2009-09-03 15:45:59 UTC (rev 6745) @@ -20,6 +20,7 @@ TYPE.fastGetDict().__setitem__("Pointer", Pointer.TYPE); } public static final CType VOID = primitive(NativeType.VOID); + public static final CType BOOL = primitive(NativeType.BOOL); public static final CType BYTE = primitive(NativeType.BYTE); public static final CType UBYTE = primitive(NativeType.UBYTE); public static final CType SHORT = primitive(NativeType.SHORT); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-03 15:02:40 UTC (rev 6744) +++ branches/ctypes-jffi/src/org/python/modules/jffi/MemoryOp.java 2009-09-03 15:45:59 UTC (rev 6745) @@ -11,6 +11,7 @@ abstract class MemoryOp { public static final MemoryOp INVALID = new InvalidOp(); public static final MemoryOp VOID = new VoidOp(); + public static final MemoryOp BOOL = new BooleanOp(); public static final MemoryOp INT8 = new Signed8(); public static final MemoryOp UINT8 = new Unsigned8(); public static final MemoryOp INT16 = new Signed16(); @@ -58,6 +59,8 @@ return POINTER; case STRING: return STRING; + case BOOL: + return BOOL; default: throw new UnsupportedOperationException("No MemoryOp for " + type); } @@ -85,6 +88,17 @@ throw Py.TypeError("Attempting to read void from memory"); } } + + private static final class BooleanOp extends MemoryOp { + public final void put(Memory mem, long offset, PyObject value) { + mem.putInt(offset, value.__nonzero__() ? 1 : 0); + } + + public final PyObject get(Memory mem, long offset) { + return Py.newBoolean(mem.getInt(offset) != 0); + } + } + static final class Signed8 extends MemoryOp { public final void put(Memory mem, long offset, PyObject value) { mem.putByte(offset, Util.int8Value(value)); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java 2009-09-03 15:02:40 UTC (rev 6744) +++ branches/ctypes-jffi/src/org/python/modules/jffi/NativeType.java 2009-09-03 15:45:59 UTC (rev 6745) @@ -4,6 +4,7 @@ public enum NativeType { VOID, + BOOL, BYTE, UBYTE, SHORT, @@ -34,6 +35,7 @@ case USHORT: return com.kenai.jffi.Type.UINT16; case INT: + case BOOL: return com.kenai.jffi.Type.SINT32; case UINT: return com.kenai.jffi.Type.UINT32; 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:02:40 UTC (rev 6744) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-03 15:45:59 UTC (rev 6745) @@ -20,6 +20,7 @@ dict.__setitem__("DynamicLibrary", DynamicLibrary.TYPE); dict.__setitem__("Type", CType.TYPE); dict.__setitem__("Function", Function.TYPE); + dict.__setitem__("CData", CData.TYPE); dict.__setitem__("PointerCData", PointerCData.TYPE); dict.__setitem__("ScalarCData", ScalarCData.TYPE); dict.__setitem__("Structure", Structure.TYPE); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <wme...@us...> - 2009-09-04 02:39:03
|
Revision: 6748 http://jython.svn.sourceforge.net/jython/?rev=6748&view=rev Author: wmeissner Date: 2009-09-04 02:38:53 +0000 (Fri, 04 Sep 2009) Log Message: ----------- When a Structure subclass is instantiated with an argument list, fill out the structure contents with the values Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-04 01:31:51 UTC (rev 6747) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-04 02:38:53 UTC (rev 6748) @@ -75,31 +75,26 @@ def build(self): return jffi.StructLayout(fields = self.fields, union = self.union) -class _StructMetaClass(type): - def __new__(cls, name, bases, dict): - try: - layout = dict['_jffi_type'] = _StructLayoutBuilder().add_fields(dict['_fields_']).build() +class _AggregateMetaClass(type): + def __new_aggregate__(cls, name, bases, dict, union = False): + if dict.has_key('_fields_'): + layout = dict['_jffi_type'] = _StructLayoutBuilder(union).add_fields(dict['_fields_']).build() # make all fields accessible via .foo for f in dict['_fields_']: dict[f[0]] = layout[f[0]] - except: - pass return type.__new__(cls, name, bases, dict) + __new_aggregate__ = staticmethod(__new_aggregate__) + +class _StructMetaClass(_AggregateMetaClass): + def __new__(cls, name, bases, dict): + return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = False) + class _UnionMetaClass(type): def __new__(cls, name, bases, dict): - try: - layout = dict['_jffi_type'] = _StructLayoutBuilder().add_fields(dict['_fields_'], union = True).build() - # make all fields accessible via .foo - for f in dict['_fields_']: - dict[f[0]] = layout[f[0]] - except: - pass + return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = True) - - return type.__new__(cls, name, bases, dict) - class Structure(jffi.Structure): __metaclass__ = _StructMetaClass @@ -107,12 +102,10 @@ __metaclass__ = _UnionMetaClass def sizeof(type): - if isinstance(type, jffi.CData): + if hasattr(type, '_jffi_type'): return type._jffi_type.size - elif hasattr(type, '_type_'): - return _TypeMap[type.__getattribute__('_type_')] else: - raise TypeError("invalid ctype") + raise TypeError("this type has no size") def alignment(type): return type._jffi_type.alignment Modified: branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java 2009-09-04 01:31:51 UTC (rev 6747) +++ branches/ctypes-jffi/src/org/python/modules/jffi/StructLayout.java 2009-09-04 02:38:53 UTC (rev 6748) @@ -1,7 +1,10 @@ package org.python.modules.jffi; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.python.core.ArgParser; import org.python.core.Py; @@ -22,15 +25,18 @@ TYPE.fastGetDict().__setitem__("ScalarField", ScalarField.TYPE); } - private final Map<PyObject, Field> fieldMap; + private final Map<Object, Field> fieldMap; + private final List<Field> fields; StructLayout(Field[] fields, com.kenai.jffi.Type struct, MemoryOp op) { super(NativeType.STRUCT, struct, op); - Map<PyObject, Field> m = new HashMap<PyObject, Field>(fields.length); + Map<Object, Field> m = new HashMap<Object, Field>(fields.length); for (Field f : fields) { m.put(f.name, f); + m.put(f.name.toString(), f); } this.fieldMap = m; + this.fields = Collections.unmodifiableList(Arrays.asList(fields)); } @ExposedType(name = "jffi.StructLayout.Field", base = PyObject.class) @@ -152,6 +158,14 @@ return fieldMap.get(name); } + Field getField(String name) { + return fieldMap.get(name); + } + + List<Field> getFieldList() { + return fields; + } + @Override public PyObject __getitem__(PyObject key) { StructLayout.Field f = getField(key); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-04 01:31:51 UTC (rev 6747) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-04 02:38:53 UTC (rev 6748) @@ -1,6 +1,9 @@ package org.python.modules.jffi; +import java.lang.reflect.Field; +import java.util.List; +import org.python.core.ArgParser; import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; @@ -30,12 +33,30 @@ public static PyObject Structure_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { - PyObject layout = subtype.__getattr__("_jffi_type"); - if (!(layout instanceof StructLayout)) { + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + if (!(jffi_type instanceof StructLayout)) { throw Py.TypeError("invalid _jffi_type for " + subtype.fastGetName() + "; should be instance of jffi.StructLayout"); } - return new Structure(subtype, (StructLayout) layout); + StructLayout layout = (StructLayout) jffi_type; + Structure s = new Structure(subtype, layout); + if (args.length > 0) { + int n = args.length - keywords.length; + List<StructLayout.Field> fields = layout.getFieldList(); + Memory m = s.getMemory(); + // First, do non-keyword args in order + for (int i = 0; i < n; ++i) { + StructLayout.Field f = fields.get(i); + f.op.put(m, f.offset, args[i]); + } + + // Now handle the keyworded args by looking up the field + for (int i = n; i < args.length; ++i) { + StructLayout.Field f = layout.getField(keywords[i - n]); + f.op.put(m, f.offset, args[i]); + } + } + return s; } protected final void initReferenceMemory(Memory m) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-04 13:50:28
|
Revision: 6750 http://jython.svn.sourceforge.net/jython/?rev=6750&view=rev Author: wmeissner Date: 2009-09-04 13:50:18 +0000 (Fri, 04 Sep 2009) Log Message: ----------- Implement from_address and in_dll for scalar, pointer, string and struct types Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java branches/ctypes-jffi/src/org/python/modules/jffi/Util.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-04 13:50:18 UTC (rev 6750) @@ -27,14 +27,19 @@ dict = { '_jffi_type': jffi.Type.Array(self, len) } return type("%s_%d" % (self.__name__, len), (_ArrayCData,), dict) -class _ScalarCData(jffi.ScalarCData): - __metaclass__ = _CTypeMetaClass +class _CData(object): + @classmethod + def in_dll(self, lib, name): + return self.from_address(lib[name]) + @classmethod def size(self): return self._jffi_type.size - size = classmethod(size) +class _ScalarCData(jffi.ScalarCData, _CData): + __metaclass__ = _CTypeMetaClass + class _ArrayCData(object): def __init__(self, *args): raise NotImplementedError("instantiating arrays is not implemented yet") @@ -76,6 +81,7 @@ return jffi.StructLayout(fields = self.fields, union = self.union) class _AggregateMetaClass(type): + @staticmethod def __new_aggregate__(cls, name, bases, dict, union = False): if dict.has_key('_fields_'): layout = dict['_jffi_type'] = _StructLayoutBuilder(union).add_fields(dict['_fields_']).build() @@ -85,8 +91,6 @@ return type.__new__(cls, name, bases, dict) - __new_aggregate__ = staticmethod(__new_aggregate__) - class _StructMetaClass(_AggregateMetaClass): def __new__(cls, name, bases, dict): return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = False) @@ -95,7 +99,7 @@ def __new__(cls, name, bases, dict): return _AggregateMetaClass.__new_aggregate__(cls, name, bases, dict, union = True) -class Structure(jffi.Structure): +class Structure(jffi.Structure, _CData): __metaclass__ = _StructMetaClass class Union(jffi.Structure): @@ -133,7 +137,7 @@ name = mod.__name__ dict["__module__"] = name - ptype = type("LP_%s" % (ctype.__name__,), (jffi.PointerCData,), dict) + ptype = type("LP_%s" % (ctype.__name__,), (jffi.PointerCData, _CData), dict) _pointer_type_cache[ctype] = ptype return ptype @@ -201,7 +205,7 @@ c_size_t = c_ulong c_ssize_t = c_long -class c_char_p(jffi.StringCData): +class c_char_p(jffi.StringCData, _CData): _type_ = 'z' _jffi_type = jffi.Type.STRING Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -2,6 +2,8 @@ package org.python.modules.jffi; import org.python.core.Py; +import org.python.core.PyInteger; +import org.python.core.PyLong; import org.python.core.PyObject; import org.python.core.PyType; import org.python.expose.ExposedMethod; @@ -15,10 +17,14 @@ private DirectMemory referenceMemory; - CData(PyType subtype, CType type) { + CData(PyType subtype, CType ctype) { + this(subtype, ctype, null); + } + + CData(PyType subtype, CType ctype, DirectMemory memory) { super(subtype); - this.ctype = type; - this.referenceMemory = null; + this.ctype = ctype; + this.referenceMemory = memory; } /** @@ -86,4 +92,15 @@ } protected abstract void initReferenceMemory(Memory m); + + + + protected static final DirectMemory findInDll(PyObject lib, PyObject name) { + if (!(lib instanceof DynamicLibrary)) { + throw Py.TypeError("expected library, not " + lib.getType().fastGetName()); + } + DynamicLibrary.Symbol sym = (DynamicLibrary.Symbol) ((DynamicLibrary) lib).find_symbol(name); + + return sym.getMemory(); + } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DynamicLibrary.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -79,13 +79,22 @@ public static final class TextSymbol extends Symbol implements ExposeAsSuperclass { public TextSymbol(DynamicLibrary lib, String name, long address) { - super(lib, name, new NativeMemory(address)); + super(lib, name, new SymbolMemory(lib, address)); } } public static final class DataSymbol extends Symbol implements ExposeAsSuperclass { public DataSymbol(DynamicLibrary lib, String name, long address) { - super(lib, name, new NativeMemory(address)); + super(lib, name, new SymbolMemory(lib, address)); } } + + private static final class SymbolMemory extends NativeMemory { + private final DynamicLibrary library; // backlink to keep library alive + + public SymbolMemory(DynamicLibrary library, long address) { + super(address); + this.library = library; + } + } } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/PointerCData.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -5,6 +5,7 @@ import org.python.core.PyNewWrapper; import org.python.core.PyObject; import org.python.core.PyType; +import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedSet; @@ -25,14 +26,8 @@ public static PyObject PointerCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { - PyObject jffi_type = subtype.__getattr__("_jffi_type"); + CType.Pointer pointerType = getPointerType(subtype); - if (!(jffi_type instanceof CType.Pointer)) { - throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); - } - - CType.Pointer pointerType = (CType.Pointer) jffi_type; - // No args == create NULL pointer if (args.length == 0) { return new PointerCData(subtype, pointerType, NullMemory.INSTANCE, pointerType.componentMemoryOp); @@ -48,6 +43,27 @@ } } + static final CType.Pointer getPointerType(PyType subtype) { + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + + if (!(jffi_type instanceof CType.Pointer)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); + } + + return (CType.Pointer) jffi_type; + } + + @ExposedClassMethod(names= { "from_address" }) + public static final PyObject from_address(PyType subtype, PyObject address) { + + CType.Pointer pointerType = getPointerType(subtype); + DirectMemory m = Util.getMemoryForAddress(address); + PointerCData cdata = new PointerCData(subtype, pointerType, m.getMemory(0), pointerType.componentMemoryOp); + cdata.setReferenceMemory(m); + + return cdata; + } + @ExposedGet(name="contents") public PyObject getContents() { return componentMemoryOp.get(getMemory(), 0); @@ -57,4 +73,5 @@ public void setContents(PyObject value) { componentMemoryOp.put(getMemory(), 0, value); } + } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/ScalarCData.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -3,10 +3,13 @@ import org.python.core.Py; import org.python.core.PyFloat; +import org.python.core.PyInteger; +import org.python.core.PyLong; import org.python.core.PyNewWrapper; import org.python.core.PyObject; import org.python.core.PyObject.ConversionException; import org.python.core.PyType; +import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; @@ -16,31 +19,46 @@ @ExposedType(name = "jffi.ScalarCData", base = CData.class) public class ScalarCData extends CData { public static final PyType TYPE = PyType.fromClass(ScalarCData.class); - + static { +// TYPE.fastGetDict().__setitem__("in_dll", new InDll()); + } private PyObject value = Py.None; @ExposedNew public static PyObject ScalarCData_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { - PyObject jffi_type = subtype.__getattr__("_jffi_type"); + ScalarCData cdata = new ScalarCData(subtype, getScalarType(subtype)); - if (!(jffi_type instanceof CType.Builtin)) { - throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); - } - - ScalarCData cdata = new ScalarCData(subtype, (CType.Builtin) jffi_type); - // If an initial value was supplied, use it, else default to zero cdata.setValue(args.length > 0 ? args[0] : Py.newInteger(0)); return cdata; } + + @ExposedClassMethod(names= { "from_address" }) + public static final PyObject from_address(PyType subtype, PyObject address) { + return new ScalarCData(subtype, getScalarType(subtype), Util.getMemoryForAddress(address)); + } + + static final CType.Builtin getScalarType(PyType subtype) { + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + + if (!(jffi_type instanceof CType.Builtin)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.getName()); + } + return (CType.Builtin) jffi_type; + } + ScalarCData(PyType pytype, CType.Builtin ctype) { super(pytype, ctype); } + ScalarCData(PyType pytype, CType.Builtin ctype, DirectMemory m) { + super(pytype, ctype, m); + } + protected final void initReferenceMemory(Memory m) { getMemoryOp().put(m, 0, value); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/StringCData.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -5,6 +5,7 @@ import org.python.core.PyNewWrapper; import org.python.core.PyObject; import org.python.core.PyType; +import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedGet; import org.python.expose.ExposedNew; import org.python.expose.ExposedSet; @@ -33,6 +34,16 @@ return new StringCData(subtype, CType.typeOf(subtype), m); } + @ExposedClassMethod(names= { "from_address" }) + public static final PyObject from_address(PyType subtype, PyObject address) { + + DirectMemory m = Util.getMemoryForAddress(address); + StringCData cdata = new StringCData(subtype, CType.typeOf(subtype), m.getMemory(0)); + cdata.setReferenceMemory(m); + + return cdata; + } + @ExposedGet(name = "value") public PyObject getValue() { Memory m = getMemory(); Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Structure.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -1,13 +1,12 @@ package org.python.modules.jffi; -import java.lang.reflect.Field; import java.util.List; -import org.python.core.ArgParser; import org.python.core.Py; import org.python.core.PyNewWrapper; import org.python.core.PyObject; import org.python.core.PyType; +import org.python.expose.ExposedClassMethod; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; @@ -33,12 +32,7 @@ public static PyObject Structure_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { - PyObject jffi_type = subtype.__getattr__("_jffi_type"); - if (!(jffi_type instanceof StructLayout)) { - throw Py.TypeError("invalid _jffi_type for " + subtype.fastGetName() + "; should be instance of jffi.StructLayout"); - } - - StructLayout layout = (StructLayout) jffi_type; + StructLayout layout = getStructLayout(subtype); Structure s = new Structure(subtype, layout); if (args.length > 0) { int n = args.length - keywords.length; @@ -59,6 +53,20 @@ return s; } + static final StructLayout getStructLayout(PyType subtype) { + PyObject jffi_type = subtype.__getattr__("_jffi_type"); + if (!(jffi_type instanceof StructLayout)) { + throw Py.TypeError("invalid _jffi_type for " + subtype.fastGetName() + "; should be instance of jffi.StructLayout"); + } + + return (StructLayout) jffi_type; + } + + @ExposedClassMethod(names= { "from_address" }) + public static final PyObject from_address(PyType subtype, PyObject address) { + return new Structure(subtype, getStructLayout(subtype), Util.getMemoryForAddress(address)); + } + protected final void initReferenceMemory(Memory m) { throw Py.RuntimeError("reference memory already initialized"); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Util.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-09-04 13:44:07 UTC (rev 6749) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Util.java 2009-09-04 13:50:18 UTC (rev 6750) @@ -129,4 +129,15 @@ + off + " size=" + len + " is out of bounds"); } } + + static final DirectMemory getMemoryForAddress(PyObject address) { + if (address instanceof Pointer) { + return ((Pointer) address).getMemory(); + } else if (address instanceof PyInteger) { + return new NativeMemory(address.asInt()); + } else if (address instanceof PyLong) { + return new NativeMemory(((PyLong) address).getValue().longValue()); + } + throw Py.TypeError("invalid address"); + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-05 05:45:44
|
Revision: 6753 http://jython.svn.sourceforge.net/jython/?rev=6753&view=rev Author: wmeissner Date: 2009-09-05 05:45:36 +0000 (Sat, 05 Sep 2009) Log Message: ----------- Hoist argtypes and restype up into jffi.Function, since the extra type info is going to be needed Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py 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/Function.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-05 01:28:02 UTC (rev 6752) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-05 05:45:36 UTC (rev 6753) @@ -240,27 +240,7 @@ _restype = c_int _argtypes = None - def set_restype(self, restype): - self._jffi_restype = restype._jffi_type - self._restype = restype - def get_restype(self): - return self._restype - - def set_argtypes(self, argtypes): - jffi_types = [] - for t in argtypes: - jffi_types.append(t._jffi_type) - self._jffi_argtypes = jffi_types - self._argtypes = argtypes - - def get_argtypes(self): - return self._argtypes - - restype = property(get_restype, set_restype) - argtypes = property(get_argtypes, set_argtypes) - - class CDLL: DEFAULT_MODE = jffi.RTLD_GLOBAL | jffi.RTLD_LAZY Modified: branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-05 01:28:02 UTC (rev 6752) +++ branches/ctypes-jffi/src/org/python/modules/jffi/DefaultInvokerFactory.java 2009-09-05 05:45:36 UTC (rev 6753) @@ -19,6 +19,16 @@ private DefaultInvokerFactory() {} + final Invoker createInvoker(com.kenai.jffi.Function function, PyObject returnType, PyObject[] parameterTypes) { + ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length]; + + for (int i = 0; i < marshallers.length; ++i) { + marshallers[i] = getMarshaller(parameterTypes[i]); + } + + return createInvoker(function, returnType, marshallers); + } + final Invoker createInvoker(com.kenai.jffi.Function function, CType[] parameterTypes, CType returnType) { ParameterMarshaller[] marshallers = new ParameterMarshaller[parameterTypes.length]; @@ -26,9 +36,12 @@ marshallers[i] = getMarshaller(parameterTypes[i]); } - - if (returnType instanceof CType.Builtin) { - switch (returnType.getNativeType()) { + return createInvoker(function, returnType, marshallers); + } + final Invoker createInvoker(com.kenai.jffi.Function function, PyObject returnType, ParameterMarshaller[] marshallers) { + CType cReturnType = CType.typeOf(returnType); + if (cReturnType instanceof CType.Builtin) { + switch (cReturnType.getNativeType()) { case VOID: return new VoidInvoker(function, marshallers); @@ -141,6 +154,10 @@ } } + private static final ParameterMarshaller getMarshaller(PyObject type) { + return getMarshaller(CType.typeOf(type)); + } + private static interface ParameterMarshaller { void marshal(HeapInvocationBuffer buffer, PyObject arg); } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-09-05 01:28:02 UTC (rev 6752) +++ branches/ctypes-jffi/src/org/python/modules/jffi/FastIntInvokerFactory.java 2009-09-05 05:45:36 UTC (rev 6753) @@ -3,6 +3,7 @@ import com.kenai.jffi.Function; import com.kenai.jffi.Platform; +import com.kenai.jffi.Type; import org.python.core.Py; import org.python.core.PyObject; @@ -63,6 +64,23 @@ } /** + * Tests if a combination of result and parameter types can be called using + * an {@link Invoker} created by this factory. + * + * @param returnType The return type of the native function. + * @param parameterTypes The parameter types of the native function. + * @return <tt>true</tt> if the method can be handled as a fast int method. + */ + final boolean isFastIntMethod(PyObject returnType, PyObject[] parameterTypes) { + for (int i = 0; i < parameterTypes.length; ++i) { + if (!isFastIntParam(parameterTypes[i])) { + return false; + } + } + return parameterTypes.length <= 3 && isFastIntResult(returnType); + } + + /** * Tests if the type can be returned as an integer result. * * @param type The result type. @@ -95,6 +113,15 @@ return false; } + /** + * Tests if the type can be returned as an integer result. + * + * @param type The result type. + * @return <tt>true</tt> if <tt>type</tt> can be returned as an integer. + */ + final boolean isFastIntResult(PyObject type) { + return isFastIntResult(CType.typeOf(type)); + } /** * Tests if the type can be passed as an integer parameter. @@ -125,6 +152,15 @@ return false; } + /** + * Tests if the type can be passed as an integer parameter. + * + * @param type The parameter type. + * @return <tt>true</tt> if <tt>type</tt> can be passed as an integer. + */ + final boolean isFastIntParam(PyObject paramType) { + return isFastIntParam(CType.typeOf(paramType)); + } /** * Creates a new <tt>Invoker</tt> instance for the given function, with the @@ -142,33 +178,66 @@ parameterConverters[i] = getIntParameterConverter(parameterTypes[i]); } if (returnType.nativeType == NativeType.FLOAT) { - switch (parameterTypes.length) { - case 0: - return new FastFloatInvokerZero(function, null, parameterConverters); - case 1: - return new FastFloatInvokerOne(function, null, parameterConverters); - case 2: - return new FastFloatInvokerTwo(function, null, parameterConverters); - case 3: - return new FastFloatInvokerThree(function, null, parameterConverters); - } + return createFloatInvoker(function, null, parameterConverters); } else { - IntResultConverter resultConverter = getIntResultConverter(returnType); - switch (parameterTypes.length) { - case 0: - return new FastIntInvokerZero(function, resultConverter, parameterConverters); - case 1: - return new FastIntInvokerOne(function, resultConverter, parameterConverters); - case 2: - return new FastIntInvokerTwo(function, resultConverter, parameterConverters); - case 3: - return new FastIntInvokerThree(function, resultConverter, parameterConverters); - } + return createIntInvoker(function, getIntResultConverter(returnType), parameterConverters); } - throw Py.RuntimeError("Fast Integer invoker does not support functions with arity=" + parameterTypes.length); } /** + * Creates a new <tt>Invoker</tt> instance for the given function, with the + * given parameter types and return type. + * + * @param function The JFFI function to wrap + * @param parameterTypes The parameter types the function will be called with + * @param returnType The result type the function will return + * @return A new {@link Invoker} instance. + */ + final Invoker createInvoker(Function function, PyObject returnType, PyObject[] parameterTypes) { + IntParameterConverter[] parameterConverters = new IntParameterConverter[parameterTypes.length]; + + for (int i = 0; i < parameterConverters.length; ++i) { + parameterConverters[i] = getIntParameterConverter(parameterTypes[i]); + } + + if (function.getReturnType().equals(Type.FLOAT)) { + return createFloatInvoker(function, null, parameterConverters); + } else { + return createIntInvoker(function, getIntResultConverter(returnType), parameterConverters); + } + } + + + final Invoker createFloatInvoker(Function function, IntResultConverter resultConverter, IntParameterConverter[] parameterConverters) { + switch (parameterConverters.length) { + case 0: + return new FastFloatInvokerZero(function, null, parameterConverters); + case 1: + return new FastFloatInvokerOne(function, null, parameterConverters); + case 2: + return new FastFloatInvokerTwo(function, null, parameterConverters); + case 3: + return new FastFloatInvokerThree(function, null, parameterConverters); + } + throw Py.RuntimeError("fast int invoker does not support functions with arity=" + parameterConverters.length); + } + + final Invoker createIntInvoker(Function function, IntResultConverter resultConverter, IntParameterConverter[] parameterConverters) { + switch (parameterConverters.length) { + case 0: + return new FastIntInvokerZero(function, resultConverter, parameterConverters); + case 1: + return new FastIntInvokerOne(function, resultConverter, parameterConverters); + case 2: + return new FastIntInvokerTwo(function, resultConverter, parameterConverters); + case 3: + return new FastIntInvokerThree(function, resultConverter, parameterConverters); + } + throw Py.RuntimeError("fast int invoker does not support functions with arity=" + parameterConverters.length); + } + + + /** * Gets a python object to integer parameter converter. * * @param type The python C type @@ -181,6 +250,15 @@ throw Py.TypeError("cannot convert objects of type " + type + " to int"); } + /** + * Gets a python object to integer parameter converter. + * + * @param type The python C type + * @return An <tt>IntParameterConverter</tt> instance. + */ + final IntParameterConverter getIntParameterConverter(PyObject type) { + return getIntParameterConverter(CType.typeOf(type)); + } /** * Gets a python object to integer parameter converter. @@ -240,6 +318,16 @@ * @param type The object type. * @return An <tt>IntResultConverter</tt> instance. */ + final IntResultConverter getIntResultConverter(PyObject type) { + return getIntResultConverter(CType.typeOf(type)); + } + + /** + * Gets a int to python object result converter for the type. + * + * @param type The object type. + * @return An <tt>IntResultConverter</tt> instance. + */ final IntResultConverter getIntResultConverter(CType type) { return type instanceof CType.Builtin ? getIntResultConverter(type.getNativeType()) : null; } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/Function.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-09-05 01:28:02 UTC (rev 6752) +++ branches/ctypes-jffi/src/org/python/modules/jffi/Function.java 2009-09-05 05:45:36 UTC (rev 6753) @@ -5,6 +5,7 @@ import org.python.core.PyList; import org.python.core.PyNewWrapper; import org.python.core.PyObject; +import org.python.core.PySequenceList; import org.python.core.PyStringMap; import org.python.core.PyType; import org.python.expose.ExposedGet; @@ -20,23 +21,20 @@ private final DynamicLibrary library; private final PyStringMap dict = new PyStringMap(); - - private volatile CType returnType = CType.INT; - private volatile CType[] parameterTypes = null; + + private volatile PyObject restype = Py.None; + private volatile PyObject[] argtypes = null; private Invoker invoker = null; @ExposedGet public final String name; - - @ExposedGet - @ExposedSet - public PyObject restype; - + Function(PyType type, Pointer address) { super(type); this.library = null; this.name = "<anonymous>"; this.pointer = address; + this.restype = type.__getattr__("_restype"); } Function(PyType type, DynamicLibrary.Symbol sym) { @@ -44,6 +42,7 @@ this.library = sym.library; this.name = sym.name; this.pointer = sym; + this.restype = type.__getattr__("_restype"); } @ExposedNew @@ -101,51 +100,41 @@ } - @ExposedGet(name = "_jffi_restype") - public PyObject getReturnType() { - return this.returnType; + @ExposedGet(name = "restype") + public PyObject getResultType() { + return this.restype; } - - @ExposedSet(name = "_jffi_restype") - public void setReturnType(PyObject returnType) { - if (!(returnType instanceof CType)) { - throw Py.TypeError("wrong argument type (expected jffi.Type)"); - } - + @ExposedSet(name = "restype") + public void setResultType(PyObject restype) { this.invoker = null; // invalidate old invoker - this.returnType = (CType) returnType; + this.restype = restype; } - - @ExposedGet(name = "_jffi_argtypes") - public PyObject getParameterTypes() { - return new PyList(parameterTypes != null ? parameterTypes : new CType[0]); + + @ExposedGet(name = "argtypes") + public PyObject getArgTypes() { + return new PyList(argtypes != null ? argtypes : new PyObject[0]); } - @ExposedSet(name = "_jffi_argtypes") - public void setParameterTypes(PyObject parameterTypes) { + @ExposedSet(name = "argtypes") + public void setArgTypes(PyObject parameterTypes) { this.invoker = null; // invalidate old invoker // Removing the parameter types defaults back to varargs if (parameterTypes == Py.None) { - this.parameterTypes = null; + this.argtypes = null; return; } - if (!(parameterTypes instanceof PyList)) { - throw Py.TypeError("wrong argument type (expected list of jffi.Type)"); + if (!(parameterTypes instanceof PySequenceList)) { + throw Py.TypeError("wrong argument type (expected list or tuple)"); } - CType[] paramTypes = new CType[((PyList) parameterTypes).size()]; - for (int i = 0; i < paramTypes.length; ++i) { - PyObject t = ((PyList) parameterTypes).pyget(i); - if (!(t instanceof CType)) { - throw Py.TypeError(String.format("wrong argument type for parameter %d (expected jffi.Type)", i)); - } - paramTypes[i] = (CType) t; + PySequenceList paramList = (PySequenceList) parameterTypes; + argtypes = new PyObject[paramList.size()]; + for (int i = 0; i < argtypes.length; ++i) { + argtypes[i] = paramList.pyget(i); } - - this.parameterTypes = paramTypes; } @Override @@ -157,25 +146,25 @@ if (invoker != null) { return invoker; } - return createInvoker(getMemory().getAddress(), returnType, parameterTypes); + return createInvoker(); } - private synchronized final Invoker createInvoker(long address, CType returnType, CType[] parameterTypes) { - if (parameterTypes == null) { + private synchronized final Invoker createInvoker() { + if (argtypes == null) { throw Py.NotImplementedError("variadic functions not supported yet; specify a parameter list"); } - com.kenai.jffi.Type jffiReturnType = NativeType.jffiType(returnType.nativeType); - com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[parameterTypes.length]; + com.kenai.jffi.Type jffiReturnType = CType.typeOf(restype).jffiType; + com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[argtypes.length]; for (int i = 0; i < jffiParamTypes.length; ++i) { - jffiParamTypes[i] = NativeType.jffiType(parameterTypes[i].nativeType); + jffiParamTypes[i] = CType.typeOf(argtypes[i]).jffiType; } - com.kenai.jffi.Function jffiFunction = new com.kenai.jffi.Function(address, jffiReturnType, jffiParamTypes); + com.kenai.jffi.Function jffiFunction = new com.kenai.jffi.Function(getMemory().getAddress(), jffiReturnType, jffiParamTypes); - if (FastIntInvokerFactory.getFactory().isFastIntMethod(returnType, parameterTypes)) { - invoker = FastIntInvokerFactory.getFactory().createInvoker(jffiFunction, parameterTypes, returnType); + if (FastIntInvokerFactory.getFactory().isFastIntMethod(restype, argtypes)) { + invoker = FastIntInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes); } else { - invoker = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, parameterTypes, returnType); + invoker = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes); } return invoker; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2009-09-11 11:39:11
|
Revision: 6786 http://jython.svn.sourceforge.net/jython/?rev=6786&view=rev Author: wmeissner Date: 2009-09-11 11:39:00 +0000 (Fri, 11 Sep 2009) Log Message: ----------- Implement memset & memmove Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CData.java branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-11 06:55:34 UTC (rev 6785) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2009-09-11 11:39:00 UTC (rev 6786) @@ -137,12 +137,18 @@ def alignment(type): return type._jffi_type.alignment -def byref(cdata): - return cdata.byref() +def addressof(cdata): + return cdata.address() +def byref(cdata, offset = 0): + return cdata.byref(offset) + def pointer(cdata): return cdata.pointer(POINTER(cdata.__class__)) +memmove = jffi.memmove +memset = jffi.memset + _pointer_type_cache = {} def POINTER(ctype): # If a pointer class for the C type has been created, re-use it Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CData.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-11 06:55:34 UTC (rev 6785) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CData.java 2009-09-11 11:39:00 UTC (rev 6786) @@ -2,8 +2,6 @@ package org.python.modules.jffi; import org.python.core.Py; -import org.python.core.PyInteger; -import org.python.core.PyLong; import org.python.core.PyObject; import org.python.core.PyType; import org.python.expose.ExposedMethod; @@ -34,8 +32,8 @@ * @return A ByReference instance pointing to this object's native memory. */ @ExposedMethod(names= { "byref" }) - public PyObject byref() { - return new ByReference(ctype, getReferenceMemory()); + public PyObject byref(PyObject offset) { + return new ByReference(ctype, (DirectMemory) getReferenceMemory().slice(offset.asInt())); } @ExposedMethod(names= { "pointer" }) @@ -47,6 +45,11 @@ return new PointerCData((PyType) pytype, CType.typeOf(pytype), getReferenceMemory(), getMemoryOp()); } + @ExposedMethod(names = { "address" }) + public PyObject address() { + return Py.newInteger(getReferenceMemory().getAddress()); + } + final CType getCType() { return ctype; } Modified: branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-11 06:55:34 UTC (rev 6785) +++ branches/ctypes-jffi/src/org/python/modules/jffi/jffi.java 2009-09-11 11:39:00 UTC (rev 6786) @@ -4,6 +4,8 @@ import com.kenai.jffi.Library; import org.python.core.ClassDictInit; import org.python.core.Py; +import org.python.core.PyInteger; +import org.python.core.PyLong; import org.python.core.PyObject; @@ -54,4 +56,30 @@ public static PyObject POINTER(PyObject type) { return type; } + + private static long getMemoryAddress(PyObject obj) { + if (obj instanceof Pointer) { + return ((Pointer) obj).getMemory().getAddress(); + } else if (obj instanceof CData) { + return ((CData) obj).getReferenceMemory().getAddress(); + } else if (obj instanceof PyInteger) { + return obj.asInt(); + } else if (obj instanceof PyLong) { + return ((PyLong) obj).asLong(0); + } else { + throw Py.TypeError("invalid memory address"); + } + } + + public static PyObject memmove(PyObject dst, PyObject src, PyObject length) { + com.kenai.jffi.MemoryIO.getInstance().copyMemory(getMemoryAddress(src), + getMemoryAddress(dst), length.asInt()); + + return Py.None; + } + + public static PyObject memset(PyObject dst, PyObject value, PyObject length) { + com.kenai.jffi.MemoryIO.getInstance().setMemory(getMemoryAddress(dst), length.asInt(), (byte) value.asInt()); + return Py.None; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <wme...@us...> - 2009-11-11 03:18:18
|
Revision: 6942 http://jython.svn.sourceforge.net/jython/?rev=6942&view=rev Author: wmeissner Date: 2009-11-11 03:18:09 +0000 (Wed, 11 Nov 2009) Log Message: ----------- Update jffi Modified Paths: -------------- branches/ctypes-jffi/build.xml branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar branches/ctypes-jffi/extlibs/jffi.jar Added Paths: ----------- branches/ctypes-jffi/extlibs/jffi-i386-Windows.jar Modified: branches/ctypes-jffi/build.xml =================================================================== --- branches/ctypes-jffi/build.xml 2009-11-09 00:08:21 UTC (rev 6941) +++ branches/ctypes-jffi/build.xml 2009-11-11 03:18:09 UTC (rev 6942) @@ -194,6 +194,7 @@ <pathelement path="${extlibs.dir}/jna-posix.jar"/> <pathelement path="${extlibs.dir}/jffi.jar"/> <pathelement path="${extlibs.dir}/jffi-Darwin.jar"/> + <pathelement path="${extlibs.dir}/jffi-i386-Windows.jar"/> <pathelement path="${extlibs.dir}/jffi-i386-SunOS.jar"/> <pathelement path="${extlibs.dir}/jffi-x86_64-SunOS.jar"/> </path> @@ -576,6 +577,7 @@ <zipfileset src="extlibs/jna.jar"/> <zipfileset src="extlibs/jffi.jar"/> <zipfileset src="extlibs/jffi-Darwin.jar"/> + <zipfileset src="extlibs/jffi-i386-Windows.jar"/> <zipfileset src="extlibs/jffi-i386-SunOS.jar"/> <zipfileset src="extlibs/jffi-x86_64-SunOS.jar"/> <zipfileset src="extlibs/jna-posix.jar"/> Modified: branches/ctypes-jffi/extlibs/jffi-i386-SunOS.jar =================================================================== (Binary files differ) Added: branches/ctypes-jffi/extlibs/jffi-i386-Windows.jar =================================================================== (Binary files differ) Property changes on: branches/ctypes-jffi/extlibs/jffi-i386-Windows.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: branches/ctypes-jffi/extlibs/jffi-x86_64-SunOS.jar =================================================================== (Binary files differ) Modified: branches/ctypes-jffi/extlibs/jffi.jar =================================================================== (Binary files differ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wme...@us...> - 2010-01-30 10:14:36
|
Revision: 6969 http://jython.svn.sourceforge.net/jython/?rev=6969&view=rev Author: wmeissner Date: 2010-01-30 10:14:30 +0000 (Sat, 30 Jan 2010) Log Message: ----------- Fixes for CType changes Modified Paths: -------------- branches/ctypes-jffi/Lib/ctypes/__init__.py branches/ctypes-jffi/src/org/python/modules/jffi/CType.java Modified: branches/ctypes-jffi/Lib/ctypes/__init__.py =================================================================== --- branches/ctypes-jffi/Lib/ctypes/__init__.py 2010-01-30 08:08:55 UTC (rev 6968) +++ branches/ctypes-jffi/Lib/ctypes/__init__.py 2010-01-30 10:14:30 UTC (rev 6969) @@ -43,7 +43,7 @@ @classmethod def size(self): - return self._jffi_type.size + return self._jffi_type.size() class _ScalarCData(jffi.ScalarCData, _CData): __metaclass__ = _CTypeMetaClass @@ -136,12 +136,12 @@ def sizeof(type): if hasattr(type, '_jffi_type'): - return type._jffi_type.size + return type._jffi_type.size() else: raise TypeError("this type has no size") def alignment(type): - return type._jffi_type.alignment + return type._jffi_type.alignment() def addressof(cdata): return cdata.address() Modified: branches/ctypes-jffi/src/org/python/modules/jffi/CType.java =================================================================== --- branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2010-01-30 08:08:55 UTC (rev 6968) +++ branches/ctypes-jffi/src/org/python/modules/jffi/CType.java 2010-01-30 10:14:30 UTC (rev 6969) @@ -96,7 +96,8 @@ } } - static abstract class Custom extends CType implements ExposeAsSuperclass { + @ExposedType(name = "jffi.Type.Custom", base = CType.class) + static class Custom extends CType { final com.kenai.jffi.Type jffiType; public Custom(NativeType type, com.kenai.jffi.Type jffiType, MemoryOp op) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |