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