summaryrefslogtreecommitdiff
path: root/testing/test_makelib.py
blob: 97e99860097dbe3b9e87caa9df7c3a523574b452 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import math
import sys
from cffi import FFIBuilder
from cffi.verifier import _get_so_suffix


def _clean_modules(tmpdir, module_name):
    sys.path.remove(str(tmpdir))
    for name in list(sys.modules.keys()):
        if name and name.endswith(module_name):
            sys.modules.pop(name)


def test_ffibuilder_makelib(tmpdir):
    builder = FFIBuilder("foo_ffi", str(tmpdir))
    builder.cdef("""
        double sin(double x);
    """)
    builder.makelib('foo', '#include <math.h>')
    builder.write_ffi_module()

    assert builder.list_built_files() == [
        'foo_ffi_foo' + _get_so_suffix(),
        'foo_ffi.py',
    ]

    sys.path.append(str(tmpdir))
    try:
        import foo_ffi
    finally:
        _clean_modules(tmpdir, 'foo_ffi')

    lib = foo_ffi.load_foo()
    assert lib.sin(12.3) == math.sin(12.3)


def test_ffibuilder_dlopen(tmpdir):
    builder = FFIBuilder("foo_ffi", str(tmpdir))
    builder.cdef("""
        double sin(double x);
    """)
    builder.add_dlopen('foo', "m")
    builder.write_ffi_module()

    assert builder.list_built_files() == [
        'foo_ffi.py',
    ]

    sys.path.append(str(tmpdir))
    try:
        import foo_ffi
    finally:
        _clean_modules(tmpdir, 'foo_ffi')

    lib = foo_ffi.load_foo()
    assert lib.sin(12.3) == math.sin(12.3)


def test_ffibuilder_makelib_and_dlopen(tmpdir):
    builder = FFIBuilder("foo_ffi", str(tmpdir))
    builder.cdef("""
        double sin(double x);
    """)
    builder.makelib('foo', '#include <math.h>')
    builder.add_dlopen('bar', "m")
    builder.write_ffi_module()

    assert builder.list_built_files() == [
        'foo_ffi_foo' + _get_so_suffix(),
        'foo_ffi.py',
    ]

    sys.path.append(str(tmpdir))
    try:
        import foo_ffi
    finally:
        _clean_modules(tmpdir, 'foo_ffi')

    lib_foo = foo_ffi.load_foo()
    assert lib_foo.sin(12.3) == math.sin(12.3)
    lib_bar = foo_ffi.load_bar()
    assert lib_bar.sin(12.3) == math.sin(12.3)


def test_ffi_module_functions(tmpdir):
    builder = FFIBuilder("foo_ffi", str(tmpdir))
    builder.cdef("""
        double sin(double x);
    """)
    builder.makelib('foo', '#include <math.h>')
    builder.write_ffi_module()

    sys.path.append(str(tmpdir))
    try:
        import foo_ffi
    finally:
        _clean_modules(tmpdir, 'foo_ffi')

    assert foo_ffi.typeof == foo_ffi._ffi.typeof
    assert foo_ffi.sizeof == foo_ffi._ffi.sizeof
    assert foo_ffi.alignof == foo_ffi._ffi.alignof
    assert foo_ffi.offsetof == foo_ffi._ffi.offsetof
    assert foo_ffi.new == foo_ffi._ffi.new
    assert foo_ffi.cast == foo_ffi._ffi.cast
    assert foo_ffi.string == foo_ffi._ffi.string
    assert foo_ffi.buffer == foo_ffi._ffi.buffer
    assert foo_ffi.callback == foo_ffi._ffi.callback
    assert foo_ffi.getctype == foo_ffi._ffi.getctype
    assert foo_ffi.gc == foo_ffi._ffi.gc

    foo_ffi.set_errno(7)
    assert foo_ffi.get_errno() == 7

    assert foo_ffi.addressof == foo_ffi._ffi.addressof
    assert foo_ffi.new_handle == foo_ffi._ffi.new_handle
    assert foo_ffi.from_handle == foo_ffi._ffi.from_handle


def test_ffi_do_some_stuff(tmpdir):
    builder = FFIBuilder("foo_ffi", str(tmpdir))
    builder.cdef("""
        enum ee { EE1, EE2, EE3, ... };
        struct foo_s { int x; int y; };
        int grid_distance(struct foo_s offset);
    """)
    builder.makelib('foo', """
        enum ee { EE1=10, EE2, EE3=-10, EE4 };
        struct foo_s { int x; int y; };
        int grid_distance(struct foo_s offset) {
            return offset.x + offset.y;
        }
    """)
    builder.write_ffi_module()

    sys.path.append(str(tmpdir))
    try:
        import foo_ffi
    finally:
        _clean_modules(tmpdir, 'foo_ffi')

    my_struct = foo_ffi.new('struct foo_s *', {'x': 1, 'y': 2})
    assert foo_ffi.typeof(my_struct) == foo_ffi.typeof("struct foo_s *")
    assert foo_ffi.sizeof('struct foo_s') == 2 * foo_ffi.sizeof('int')
    assert foo_ffi.alignof('struct foo_s') == foo_ffi.sizeof('int')
    assert foo_ffi.typeof(foo_ffi.cast('long', 42)) == foo_ffi.typeof('long')
    assert foo_ffi.string(foo_ffi.new('char *', b"\x00")) == b""
    assert foo_ffi.string(foo_ffi.cast('enum ee', 11)) == "EE2"
    assert foo_ffi.string(foo_ffi.cast('enum ee', -10)) == "EE3"

    def cb(n):
        return n + 1
    f = foo_ffi.callback("int(*)(int)", cb)
    assert f(1) == 2

    lib = foo_ffi.load_foo()
    assert lib.grid_distance(my_struct[0]) == 3