~ubuntu-branches/ubuntu/trusty/python-cffi/trusty-proposed

« back to all changes in this revision

Viewing changes to demo/pyobj.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-01-18 11:36:40 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140118113640-1fb2r3isjhkvn5za
Tags: 0.8.1-0ubuntu1
* New upstream version.
* Ignore test results for python 3.4, see lp #1270401 and
  see https://bitbucket.org/cffi/cffi/issue/135.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
referents = []     # list "object descriptor -> python object"
 
3
freelist = None
 
4
 
 
5
def store(x):
 
6
    "Store the object 'x' and returns a new object descriptor for it."
 
7
    global freelist
 
8
    p = freelist
 
9
    if p is None:
 
10
        p = len(referents)
 
11
        referents.append(x)
 
12
    else:
 
13
        freelist = referents[p]
 
14
        referents[p] = x
 
15
    return p
 
16
 
 
17
def discard(p):
 
18
    """Discard (i.e. close) the object descriptor 'p'.
 
19
    Return the original object that was attached to 'p'."""
 
20
    global freelist
 
21
    x = referents[p]
 
22
    referents[p] = freelist
 
23
    freelist = p
 
24
    return x
 
25
 
 
26
class Ref(object):
 
27
    """For use in 'with Ref(x) as ob': open an object descriptor
 
28
    and returns it in 'ob', and close it automatically when the
 
29
    'with' statement finishes."""
 
30
    def __init__(self, x):
 
31
        self.x = x
 
32
    def __enter__(self):
 
33
        self.p = p = store(self.x)
 
34
        return p
 
35
    def __exit__(self, *args):
 
36
        discard(self.p)
 
37
 
 
38
def count_pyobj_alive():
 
39
    result = len(referents)
 
40
    p = freelist
 
41
    while p is not None:
 
42
        assert result > 0
 
43
        result -= 1
 
44
        p = referents[p]
 
45
    return result
 
46
 
 
47
# ------------------------------------------------------------
 
48
 
 
49
if __name__ == '__main__':
 
50
    import api
 
51
 
 
52
    ffi = api.PythonFFI()
 
53
 
 
54
    ffi.cdef("""
 
55
        typedef int pyobj_t;
 
56
        int sum_integers(pyobj_t p_list);
 
57
        pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial);
 
58
    """)
 
59
 
 
60
    @ffi.pyexport("int(pyobj_t)")
 
61
    def length(p_list):
 
62
        list = referents[p_list]
 
63
        return len(list)
 
64
 
 
65
    @ffi.pyexport("int(pyobj_t, int)")
 
66
    def getitem(p_list, index):
 
67
        list = referents[p_list]
 
68
        return list[index]
 
69
 
 
70
    @ffi.pyexport("pyobj_t(pyobj_t)")
 
71
    def pyobj_dup(p):
 
72
        return store(referents[p])
 
73
 
 
74
    @ffi.pyexport("void(pyobj_t)")
 
75
    def pyobj_close(p):
 
76
        discard(p)
 
77
 
 
78
    @ffi.pyexport("pyobj_t(pyobj_t, int)")
 
79
    def pyobj_getitem(p_list, index):
 
80
        list = referents[p_list]
 
81
        return store(list[index])
 
82
 
 
83
    @ffi.pyexport("pyobj_t(pyobj_t, pyobj_t)")
 
84
    def pyobj_add(p1, p2):
 
85
        return store(referents[p1] + referents[p2])
 
86
 
 
87
    lib = ffi.verify("""
 
88
        typedef int pyobj_t;    /* an "object descriptor" number */
 
89
 
 
90
        int sum_integers(pyobj_t p_list) {
 
91
            /* this a demo function written in C, using the API
 
92
               defined above: length() and getitem(). */
 
93
            int i, result = 0;
 
94
            int count = length(p_list);
 
95
            for (i=0; i<count; i++) {
 
96
                int n = getitem(p_list, i);
 
97
                result += n;
 
98
            }
 
99
            return result;
 
100
        }
 
101
 
 
102
        pyobj_t sum_objects(pyobj_t p_list, pyobj_t p_initial) {
 
103
            /* same as above, but keeps all additions as Python objects */
 
104
            int i;
 
105
            int count = length(p_list);
 
106
            pyobj_t p1 = pyobj_dup(p_initial);
 
107
            for (i=0; i<count; i++) {
 
108
                pyobj_t p2 = pyobj_getitem(p_list, i);
 
109
                pyobj_t p3 = pyobj_add(p1, p2);
 
110
                pyobj_close(p2);
 
111
                pyobj_close(p1);
 
112
                p1 = p3;
 
113
            }
 
114
            return p1;
 
115
        }
 
116
    """)
 
117
 
 
118
    with Ref([10, 20, 30, 40]) as p_list:
 
119
        print lib.sum_integers(p_list)
 
120
        with Ref(5) as p_initial:
 
121
            result = discard(lib.sum_objects(p_list, p_initial))
 
122
            print result
 
123
 
 
124
    assert count_pyobj_alive() == 0