Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Commit [758895] ctypes-via-rawffi Maximize Restore History

Initial implementation of _rawffi via jffi. Not really useful, but enough to implement simple integer functions, e.g. getpid()

wmeissner@79b11f02-f210-0410-99aa-fb189b3d1ac4 wmeissner@79b11f02-f210-0410-99aa-fb189b3d1ac4 2009-05-04

added extlibs/jffi.jar
added src/org/python/modules/_rawffi/BoundedNativeMemory.java
added src/org/python/modules/_rawffi/CDLL.java
added src/org/python/modules/_rawffi/CallbackPtr.java
added src/org/python/modules/_rawffi/DefaultInvokerFactory.java
added src/org/python/modules/_rawffi/DirectMemory.java
added src/org/python/modules/_rawffi/FastIntInvokerFactory.java
added src/org/python/modules/_rawffi/FixedArityInvoker.java
added src/org/python/modules/_rawffi/FuncPtr.java
added src/org/python/modules/_rawffi/HeapMemory.java
added src/org/python/modules/_rawffi/Memory.java
added src/org/python/modules/_rawffi/MemoryOp.java
added src/org/python/modules/_rawffi/NativeMemory.java
added src/org/python/modules/_rawffi/NativeType.java
added src/org/python/modules/_rawffi/RawFFI.java
added src/org/python/modules/_rawffi/Type.java
added src/org/python/modules/_rawffi/Util.java
changed CoreExposed.includes
changed build.xml
changed src/org/python/modules/Setup.java
copied Lib/_rawffi.py -> src/org/python/modules/_rawffi/Array.java
extlibs/jffi.jar Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/BoundedNativeMemory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/CDLL.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/CallbackPtr.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/DefaultInvokerFactory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/DirectMemory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/FastIntInvokerFactory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/FixedArityInvoker.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/FuncPtr.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/HeapMemory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/Memory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/MemoryOp.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/NativeMemory.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/NativeType.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/RawFFI.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/Type.java Diff Switch to side-by-side view
Loading...
src/org/python/modules/_rawffi/Util.java Diff Switch to side-by-side view
Loading...
CoreExposed.includes Diff Switch to side-by-side view
Loading...
build.xml Diff Switch to side-by-side view
Loading...
src/org/python/modules/Setup.java Diff Switch to side-by-side view
Loading...
Lib/_rawffi.py to src/org/python/modules/_rawffi/Array.java
--- a/Lib/_rawffi.py
+++ b/src/org/python/modules/_rawffi/Array.java
@@ -1,204 +1,181 @@
-import com.sun.jna as jna
-from java.lang import Short, Character
-import sys
 
-def get_libc():
-    return CDLL("c")
+package org.python.modules._rawffi;
 
-FUNCFLAG_STDCALL = 0
-FUNCFLAG_CDECL     = 1  # for WINAPI calls
-FUNCFLAG_PYTHONAPI = 4
+import org.python.core.ArgParser;
+import org.python.core.Py;
+import org.python.core.PyInteger;
+import org.python.core.PyList;
+import org.python.core.PyObject;
+import org.python.core.PyString;
+import org.python.core.PyTuple;
+import org.python.core.PyType;
+import org.python.expose.ExposedGet;
+import org.python.expose.ExposedType;
 
-# XXX hardcoded
-typecode_map = {'h': 2, 'H': 2,
-                'c': 1, 'p': 4,
-                's': 4, 'P': 4,
-                'i': 4, 'O': 4,
-                'l': 4, 'L': 4,
-                'f': 4, 'd': 8,
-                'q': 8, 'Q': 8,
-                'b': 1, 'B': 1,
-                'z': 4, 'Z': 4,
-                'u': 2}
+@ExposedType(name = "_rawffi.Array", base = PyObject.class)
+public class Array extends PyObject {
+    public static final PyType TYPE = PyType.fromClass(Array.class);
 
-# set up of machine internals
-_bits = 0
-_itest = 1
-_Ltest = 1L
-while _itest == _Ltest and type(_itest) is int:
-    _itest *= 2
-    _Ltest *= 2
-    _bits += 1
+    private final Type type;
+    private final MemoryOp mop;
 
-LONG_BIT = _bits+1
-LONG_MASK = _Ltest*2-1
-LONG_TEST = _Ltest
+    public Array(PyString typeCode) {
+        type = Type.parseTypeString(typeCode.asString());
+        mop = MemoryOp.getMemoryOp(type.getNativeType());
+    }
 
-def intmask(n):
-    if isinstance(n, int):
-        return int(n)   # possibly bool->int
-    n = long(n)
-    n &= LONG_MASK
-    if n >= LONG_TEST:
-        n -= 2*LONG_TEST
-    return int(n)
+    @Override
+    public PyObject __call__(PyObject[] args, String[] keywords) {
+        ArgParser ap = new ArgParser("__call__", args, keywords,
+                new String[] { "size", "items", "autofree" });
+        int size = ap.getInt(0);
+        PyObject items = ap.getPyObject(1, Py.None);
+        boolean autofree = ap.getPyObject(2, Py.False).asInt() != 0;
 
-class Array(object):
-    def __init__(self, typecode):
-        self.typecode = typecode
-        self.itemsize = typecode_map[typecode]
+        Instance array = autofree
+                ? new NoAutoFree(type, mop, size) : new AutoFree(type, mop, size);
 
-    def allocate(self, size, autofree=False):
-        if not autofree:
-            return ArrayInstanceNoAutoFree(self, size)
-        return ArrayInstance(self, size)
+        if (items instanceof PyList) {
+            int index = 0;
+            for (PyObject obj: items.asIterable()) {
+                array.put(index++, obj);
+            }
+        }
+        System.out.println("size=" + size + " items=" + items + " autofree=" + autofree);
 
-    def __call__(self, size, items=None, autofree=False):
-        res = self.allocate(size, autofree)
-        if items is not None:
-            for i, item in enumerate(items):
-                res[i] = item
-        return res
+        return array;
+    }
 
-    def size_alignment(self, lgt):
-        return sizeof(self.typecode) * lgt, alignment(self.typecode)
+    public PyObject size_alignment(PyInteger length) {
+        PyInteger size = Py.newInteger(length.asInt() * type.size());
+        PyInteger alignment = Py.newInteger(type.alignment());
+        return new PyTuple(size, alignment);
+    }
 
-class ArrayInstanceNoAutoFree(object):
-    def __init__(self, shape, size):
-        self.shape = shape
-        self.alloc = jna.Pointer(jna.Memory.malloc(size * shape.itemsize))
+    static Instance box(Type type, PyObject value) {
+        Instance array = new AutoFree(type, type.getMemoryOp(), 1);
+        array.put(0, value);
+        return array;
+    }
 
-    def __setitem__(self, index, value):
-        if self.shape.itemsize == 1:
-            self.alloc.setByte(index, ord(value))
-        elif self.shape.itemsize == 2:
-            self.alloc.setShort(index, value)
-        elif self.shape.itemsize == 4:
-            self.alloc.setInt(index, value)
-        else:
-            xxx
+    static Instance box(Type type, byte value) {
+        Instance array = new AutoFree(type, type.getMemoryOp(), 1);
+        array.getMemory().putByte(0, value);
+        return array;
+    }
 
-    def __getitem__(self, index):
-        if self.shape.itemsize == 1:
-            return chr(self.alloc.getByte(index))
-        elif self.shape.itemsize == 2:
-            return self.alloc.getShort(index)
-        elif self.shape.itemsize == 4:
-            return self.alloc.getInt(index)
-        else:
-            xxx
+    static Instance box(Type type, short value) {
+        Instance array = new AutoFree(type, type.getMemoryOp(), 1);
+        array.getMemory().putShort(0, value);
+        return array;
+    }
 
-    def free(self):
-        jna.Memory.free(self.alloc.peer)
+    static Instance box(Type type, int value) {
+        Instance array = new AutoFree(type, type.getMemoryOp(), 1);
+        array.getMemory().putInt(0, value);
+        return array;
+    }
 
-    def byptr(self):
-        a = Array('p')(1)
-        a[0] = intmask(self.alloc.peer)
-        return a
+    static Instance box(Type type) {
+        return new AutoFree(type, type.getMemoryOp(), 1);
+    }
+    
+    @ExposedType(name = "_rawffi.Array.Instance", base = PyObject.class)
+    static class Instance extends PyObject {
+        public static final PyType TYPE = PyType.fromClass(Instance.class);
+        protected static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
 
-    def getbuffer(self):
-        return self.alloc.peer
+        protected final Type type;
+        protected final MemoryOp mop;
+        protected final int length;
+        protected final DirectMemory memory;
 
-    def setbuffer(self, i):
-        self.alloc.peer = i
+        Instance(Type type, MemoryOp mop, int length) {
+            this.type = type;
+            this.mop = mop;
+            this.length = length;
+            final int msize = type.size() * length;
+            this.memory = new BoundedNativeMemory(IO.allocateMemory(msize, true), msize);
+            if (this.memory.getAddress() == 0L) {
+                throw Py.MemoryError(String.format("Failed to allocate memory for %d items of size %d",
+                        length, type.size()));
+            }
+        }
+        private final int offset(int index) {
+            return index * type.size();
+        }
 
-    buffer = property(getbuffer, setbuffer)
+        void put(int index, PyObject value) {
+            mop.put(memory, offset(index), value);
+        }
 
-class ArrayInstance(ArrayInstanceNoAutoFree):
-    def __del__(self):
-        self.free()
+        PyObject get(int index) {
+            return mop.get(memory, offset(index));
+        }
 
-class FuncPtr(object):
-    def __init__(self, fn, argtypes, restype, flags=0):
-        if isinstance(fn, (int, long)):
-            self.fn = jna.Function(jna.Pointer(fn), FUNCFLAG_STDCALL)
-        else:
-            self.fn = fn
-        self.argtypes = argtypes
-        self.restype = restype
+        Memory getMemory() {
+            return memory;
+        }
 
-    def __call__(self, *args):
-        container = Array(self.restype)(1, autofree=True)
-        _args = [self._convert(t, i[0]) for t, i in zip(self.argtypes, args)]
-        res = self.fn.invokeInt(_args)
-        if self.restype == 'c':
-            container[0] = chr(res)
-        else:
-            container[0] = res
-            
-        return container
+        @Override
+        public int __len__() {
+            return length;
+        }
+
+
+        @Override
+        public PyObject __finditem__(PyObject key) {
+            return get(key.asInt());
+        }
+
+        @Override
+        public PyObject __finditem__(int key) {
+            return get(key);
+        }
+
+        @Override
+        public void __setitem__(PyObject key, PyObject value) {
+            put(key.asInt(), value);
+        }
+
+        @Override
+        public void __setitem__(int key, PyObject value) {
+            put(key, value);
+        }
+
+        @ExposedGet(name = "buffer")
+        public PyObject buffer() {
+            return this;
+        }
+    }
+
+    static final class NoAutoFree extends Instance {
+
+        public NoAutoFree(Type type, MemoryOp mop, int length) {
+            super(type, mop, length);
+        }
+
+        public void free() {
+            IO.freeMemory(memory.getAddress());
+        }
+
+    }
+
+    static final class AutoFree extends Instance {
+
+        public AutoFree(Type type, MemoryOp mop, int length) {
+            super(type, mop, length);
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                IO.freeMemory(memory.getAddress());
+            } finally {
+                super.finalize();
+            }
+        }
+    }
     
-    def byptr(self):
-        a = Array('p')(1)
-        a[0] = intmask(self.fn.peer)
-        return a
 
-    def _convert(self, t, v):
-        if t == 'c':
-            return Character(v)
-        elif t == 'h':
-            return Short(v)
-        return v
-
-# XXX dummy obj
-class CallbackPtr(object):
-    def __init__(self, tp, callable, args, result):
-        pass
-
-    def byptr(self):
-        a = Array('p')(1)
-        a[0] = 0
-        return a
-
-class CDLL(object):
-    def __init__(self, libname):
-        self.lib = jna.NativeLibrary.getInstance(libname)
-        self.cache = dict()
-
-    def ptr(self, name, argtypes, restype, flags=0):
-        key = (name, tuple(argtypes), restype)
-        try:
-            return self.cache[key]
-        except KeyError:
-            fn = self.lib.getFunction(name)
-            fnp = FuncPtr(fn, argtypes, restype, flags)
-            self.cache[key] = fnp
-            return fnp
-
-    def getaddressindll(self, symbol):
-        return self.lib.getFunction(symbol).peer
-
-def sizeof(s):
-    return typecode_map[s]
-
-def alignment(s):
-    return 1
-
-def charp2string(s_p):
-    if s_p == 0:
-        return None
-    a = jna.Memory()
-    a.size = sys.maxint
-    a.peer = s_p
-    i = 0
-    l = []
-    while True:
-        c = chr(a.getByte(i))
-        if c == '\x00':
-            return ''.join(l)
-        l.append(c)
-        i += 1
-
-def charp2rawstring(s_p, size=-1):
-    if size == -1:
-        return charp2string(s_p)
-    else:
-        a = jna.Memory()
-        a.size = sys.maxint
-        a.peer = s_p
-        l = []
-        for i in range(size):
-            c = chr(a.getByte(i))
-            l.append(c)
-            i += 1
-        return ''.join(l)
+}