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
|
from cffi import FFI
class FakeBackend(object):
def nonstandard_integer_types(self):
return {}
def sizeof(self, name):
return 1
def load_library(self, name):
assert "libc" in name or "libm" in name
return FakeLibrary()
def new_function_type(self, args, result, has_varargs):
return '<func (%s), %s, %s>' % (', '.join(args), result, has_varargs)
def new_primitive_type(self, name):
assert name == name.lower()
return '<%s>' % name
def new_pointer_type(self, itemtype):
return '<pointer to %s>' % (itemtype,)
def new_struct_type(self, name):
return FakeStruct(name)
def complete_struct_or_union(self, s, fields, tp=None):
assert isinstance(s, FakeStruct)
s.fields = fields
def new_array_type(self, ptrtype, length):
return '<array %s x %s>' % (ptrtype, length)
class FakeStruct(object):
def __init__(self, name):
self.name = name
def __str__(self):
return ', '.join([y + x for x, y, z in self.fields])
class FakeLibrary(object):
def load_function(self, BType, name):
return FakeFunction(BType, name)
class FakeFunction(object):
def __init__(self, BType, name):
self.BType = BType
self.name = name
def test_simple():
ffi = FFI(backend=FakeBackend())
ffi.cdef("double sin(double x);")
m = ffi.load("m")
func = m.sin # should be a callable on real backends
assert func.name == 'sin'
assert func.BType == '<func (<double>), <double>, False>'
def test_pipe():
ffi = FFI(backend=FakeBackend())
ffi.cdef("int pipe(int pipefd[2]);")
func = ffi.C.pipe
assert func.name == 'pipe'
assert func.BType == '<func (<pointer to <int>>), <int>, False>'
def test_vararg():
ffi = FFI(backend=FakeBackend())
ffi.cdef("short foo(int, ...);")
func = ffi.C.foo
assert func.name == 'foo'
assert func.BType == '<func (<int>), <short>, True>'
def test_no_args():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
int foo(void);
""")
assert ffi.C.foo.BType == '<func (), <int>, False>'
def test_typedef():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef unsigned int UInt;
typedef UInt UIntReally;
UInt foo(void);
""")
assert ffi.typeof("UIntReally") == '<unsigned int>'
assert ffi.C.foo.BType == '<func (), <unsigned int>, False>'
def test_typedef_more_complex():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef struct { int a, b; } foo_t, *foo_p;
int foo(foo_p[]);
""")
assert str(ffi.typeof("foo_t")) == '<int>a, <int>b'
assert ffi.typeof("foo_p") == '<pointer to <int>a, <int>b>'
assert ffi.C.foo.BType == ('<func (<pointer to <pointer to '
'<int>a, <int>b>>), <int>, False>')
def test_typedef_array_force_pointer():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef int array_t[5];
""")
type = ffi._parser.parse_type("array_t", force_pointer=True)
BType = ffi._get_cached_btype(type)
assert BType == '<array <pointer to <int>> x 5>'
def test_typedef_array_convert_array_to_pointer():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef int (*fn_t)(int[5]);
""")
type = ffi._parser.parse_type("fn_t")
BType = ffi._get_cached_btype(type)
assert BType == '<func (<pointer to <int>>), <int>, False>'
|