src.org.python.modules.jffi.Function Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-standalone Show documentation
Show all versions of jython-standalone Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
package org.python.modules.jffi;
import com.kenai.jffi.CallingConvention;
import org.python.core.Py;
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.core.Traverseproc;
import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedSet;
import org.python.expose.ExposedType;
@ExposedType(name = "jffi.Function", base = PyObject.class)
public class Function extends BasePointer implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(Function.class);
private final Pointer pointer;
private final DynamicLibrary library;
private final PyStringMap dict = new PyStringMap();
private volatile PyObject restype = CType.INT;
private volatile PyObject[] argtypes = null;
private Invoker defaultInvoker;
private Invoker compiledInvoker;
private volatile JITHandle jitHandle;
private volatile com.kenai.jffi.Function jffiFunction;
@ExposedGet
public PyObject errcheck = Py.None;
@ExposedGet
public final String name;
Function(PyType type, Pointer address) {
super(type);
this.library = null;
this.name = "";
this.pointer = address;
this.restype = type.__getattr__("_restype");
}
Function(PyType type, DynamicLibrary.Symbol sym) {
super(type);
this.library = sym.library;
this.name = sym.name;
this.pointer = sym;
this.restype = type.__getattr__("_restype");
}
@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) {
return new Function(subtype, (DynamicLibrary.Symbol) args[0]);
} else {
return new Function(subtype, (Pointer) args[0]);
}
} else {
throw Py.TypeError("expected memory address");
}
}
public DirectMemory getMemory() {
return pointer.getMemory();
}
@Override
public PyObject fastGetDict() {
return dict;
}
@Override
public PyObject getDict() {
return dict;
}
@Override
public PyObject __call__(PyObject[] args, String[] keywords) {
return getInvoker().invoke(args);
}
@Override
public PyObject __call__() {
return getInvoker().invoke();
}
@Override
public PyObject __call__(PyObject arg0) {
return getInvoker().invoke(arg0);
}
@Override
public PyObject __call__(PyObject arg0, PyObject arg1) {
return getInvoker().invoke(arg0, arg1);
}
@Override
public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2) {
return getInvoker().invoke(arg0, arg1, arg2);
}
@Override
public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2, PyObject arg3) {
return getInvoker().invoke(arg0, arg1, arg2, arg3);
}
@ExposedGet(name = "restype")
public PyObject getResultType() {
return this.restype;
}
@ExposedSet(name = "restype")
public void setResultType(PyObject restype) {
invalidateInvoker();
this.restype = restype;
}
@ExposedGet(name = "argtypes")
public PyObject getArgTypes() {
return new PyList(argtypes != null ? argtypes : new PyObject[0]);
}
@ExposedSet(name = "argtypes")
public void setArgTypes(PyObject parameterTypes) {
invalidateInvoker();
// Removing the parameter types defaults back to varargs
if (parameterTypes == Py.None) {
this.argtypes = null;
return;
}
if (!(parameterTypes instanceof PySequenceList)) {
throw Py.TypeError("wrong argument type (expected list or tuple)");
}
PySequenceList paramList = (PySequenceList) parameterTypes;
argtypes = new PyObject[paramList.size()];
for (int i = 0; i < argtypes.length; ++i) {
argtypes[i] = paramList.pyget(i);
}
}
@ExposedSet(name = "errcheck")
public void errcheck(PyObject errcheck) {
invalidateInvoker();
this.errcheck = errcheck;
}
@Override
public boolean __nonzero__() {
return !getMemory().isNull();
}
protected final Invoker getInvoker() {
return compiledInvoker != null ? compiledInvoker : tryCompilation();
}
private synchronized Invoker tryCompilation() {
if (compiledInvoker != null) {
return compiledInvoker;
}
if (argtypes == null) {
throw Py.NotImplementedError("variadic functions not supported yet; specify a parameter list");
}
CType cResultType = CType.typeOf(restype);
CType[] cParameterTypes = new CType[argtypes.length];
for (int i = 0; i < cParameterTypes.length; i++) {
cParameterTypes[i] = CType.typeOf(argtypes[i]);
}
if (jitHandle == null) {
jitHandle = JITCompiler.getInstance().getHandle(cResultType, cParameterTypes, CallingConvention.DEFAULT, false);
}
if (jffiFunction == null) {
com.kenai.jffi.Type jffiReturnType = Util.jffiType(cResultType);
com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[argtypes.length];
for (int i = 0; i < jffiParamTypes.length; ++i) {
jffiParamTypes[i] = Util.jffiType(cParameterTypes[i]);
}
jffiFunction = new com.kenai.jffi.Function(getMemory().getAddress(), jffiReturnType, jffiParamTypes);
}
if (defaultInvoker == null) {
Invoker invoker = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
defaultInvoker = errcheck != Py.None ? new ErrCheckInvoker(invoker, errcheck) : invoker;
}
Invoker invoker = jitHandle.compile(jffiFunction, null, new NativeDataConverter[0]);
if (invoker != null) {
return compiledInvoker = errcheck != Py.None ? new ErrCheckInvoker(invoker, errcheck) : invoker;
}
//
// Once compilation has failed, always fallback to the default invoker
//
if (jitHandle.compilationFailed()) {
compiledInvoker = defaultInvoker;
}
return defaultInvoker;
}
private synchronized void invalidateInvoker() {
// null out the invoker - it will be regenerated on next invocation
this.defaultInvoker = null;
this.compiledInvoker = null;
this.jitHandle = null;
this.jffiFunction = null;
}
private static final class ErrCheckInvoker extends Invoker {
private final Invoker invoker;
private final PyObject errcheck;
public ErrCheckInvoker(Invoker invoker, PyObject errcheck) {
this.invoker = invoker;
this.errcheck = errcheck;
}
public PyObject invoke(PyObject[] args) {
return errcheck.__call__(invoker.invoke(args));
}
public PyObject invoke() {
return errcheck.__call__(invoker.invoke());
}
public PyObject invoke(PyObject arg1) {
return errcheck.__call__(invoker.invoke(arg1));
}
public PyObject invoke(PyObject arg1, PyObject arg2) {
return errcheck.__call__(invoker.invoke(arg1, arg2));
}
public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3) {
return errcheck.__call__(invoker.invoke(arg1, arg2, arg3));
}
public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4) {
return errcheck.__call__(invoker.invoke(arg1, arg2, arg3, arg4));
}
public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5) {
return errcheck.__call__(invoker.invoke(arg1, arg2, arg3, arg4, arg5));
}
public PyObject invoke(PyObject arg1, PyObject arg2, PyObject arg3, PyObject arg4, PyObject arg5, PyObject arg6) {
return errcheck.__call__(invoker.invoke(arg1, arg2, arg3, arg4, arg5, arg6));
}
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
int res = 0;
if (pointer != null && pointer instanceof PyObject) {
res = visit.visit((PyObject) pointer, arg);
if (res != 0) {
return res;
}
}
if (dict != null) {
res = visit.visit(dict, arg);
if (res != 0) {
return res;
}
}
if (restype != null) {
res = visit.visit(restype, arg);
if (res != 0) {
return res;
}
}
if (argtypes != null) {
for (PyObject obj: argtypes) {
res = visit.visit(obj, arg);
if (res != 0) {
return res;
}
}
}
return 0;
}
@Override
public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
if (ob != null && (pointer == ob || dict == ob || restype == ob)) {
return true;
};
if (argtypes != null)
{
for (PyObject obj: argtypes) {
if (obj == ob) {
return true;
}
}
}
return false;
}
}