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 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.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 Pointer {
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 = Py.None;
private volatile PyObject[] argtypes = null;
private Invoker invoker = null;
@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);
}
@ExposedGet(name = "restype")
public PyObject getResultType() {
return this.restype;
}
@ExposedSet(name = "restype")
public void setResultType(PyObject restype) {
this.invoker = null; // invalidate old invoker
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) {
this.invoker = null; // invalidate old invoker
// 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) {
this.invoker = null; // invalidate old invoker
this.errcheck = errcheck;
}
@Override
public boolean __nonzero__() {
return !getMemory().isNull();
}
private final Invoker getInvoker() {
if (invoker != null) {
return invoker;
}
return createInvoker();
}
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 = Util.jffiType(CType.typeOf(restype));
com.kenai.jffi.Type[] jffiParamTypes = new com.kenai.jffi.Type[argtypes.length];
for (int i = 0; i < jffiParamTypes.length; ++i) {
jffiParamTypes[i] = Util.jffiType(CType.typeOf(argtypes[i]));
}
com.kenai.jffi.Function jffiFunction = new com.kenai.jffi.Function(getMemory().getAddress(), jffiReturnType, jffiParamTypes);
Invoker i;
if (FastIntInvokerFactory.getFactory().isFastIntMethod(restype, argtypes)) {
i = FastIntInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
} else {
i = DefaultInvokerFactory.getFactory().createInvoker(jffiFunction, restype, argtypes);
}
return invoker = errcheck != Py.None ? new ErrCheckInvoker(i, errcheck) : i;
}
private static final class ErrCheckInvoker implements 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));
}
}
}