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] |