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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
|
from rpython.flowspace.model import const
from rpython.flowspace.objspace import build_flow
from rpython.translator.simplify import simplify_graph
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.cparser import parse_source, CTypeSpace
def test_configure():
decl = """
typedef ssize_t Py_ssize_t;
typedef struct {
Py_ssize_t ob_refcnt;
Py_ssize_t ob_pypy_link;
double ob_fval;
} TestFloatObject;
"""
cts = parse_source(decl)
TestFloatObject = cts.definitions['TestFloatObject']
assert isinstance(TestFloatObject, lltype.Struct)
assert TestFloatObject.c_ob_refcnt == rffi.SSIZE_T
assert TestFloatObject.c_ob_pypy_link == rffi.SSIZE_T
assert TestFloatObject.c_ob_fval == rffi.DOUBLE
def test_simple():
decl = "typedef ssize_t Py_ssize_t;"
cts = parse_source(decl)
assert cts.definitions == {'Py_ssize_t': rffi.SSIZE_T}
def test_macro():
decl = """
typedef ssize_t Py_ssize_t;
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
Py_ssize_t ob_pypy_link; \
typedef struct {
PyObject_HEAD
double ob_fval;
} PyFloatObject;
"""
cts = parse_source(decl)
assert 'PyFloatObject' in cts.definitions
assert 'PyObject_HEAD' in cts.macros
def test_include():
cdef1 = """
typedef ssize_t Py_ssize_t;
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
Py_ssize_t ob_pypy_link; \
typedef struct {
char *name;
} Type;
"""
cdef2 = """
typedef struct {
PyObject_HEAD
Py_ssize_t ob_foo;
Type *type;
} Object;
"""
cts1 = parse_source(cdef1)
Type = cts1.definitions['Type']
assert isinstance(Type, lltype.Struct)
cts2 = parse_source(cdef2, includes=[cts1])
assert 'Type' not in cts2.definitions
Object = cts2.definitions['Object']
assert Object.c_type.TO is Type
def test_multiple_sources():
cdef1 = """
typedef ssize_t Py_ssize_t;
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
Py_ssize_t ob_pypy_link; \
typedef struct {
char *name;
} Type;
"""
cdef2 = """
typedef struct {
PyObject_HEAD
Py_ssize_t ob_foo;
Type *type;
} Object;
"""
cts = CTypeSpace()
cts.parse_source(cdef1)
Type = cts.definitions['Type']
assert isinstance(Type, lltype.Struct)
assert 'Object' not in cts.definitions
cts.parse_source(cdef2)
Object = cts.definitions['Object']
assert Object.c_type.TO is Type
def test_incomplete():
cdef = """
typedef ssize_t Py_ssize_t;
typedef struct {
Py_ssize_t ob_refcnt;
Py_ssize_t ob_pypy_link;
struct _typeobject *ob_type;
} Object;
typedef struct {
void *buf;
Object *obj;
} Buffer;
"""
cts = parse_source(cdef)
Object = cts.gettype('Object')
assert isinstance(Object, lltype.Struct)
def test_recursive():
cdef = """
typedef ssize_t Py_ssize_t;
typedef struct {
Py_ssize_t ob_refcnt;
Py_ssize_t ob_pypy_link;
struct _typeobject *ob_type;
} Object;
typedef struct {
void *buf;
Object *obj;
} Buffer;
typedef struct _typeobject {
Object *obj;
} Type;
"""
cts = parse_source(cdef)
Object = cts.definitions['Object']
assert isinstance(Object, lltype.Struct)
hash(Object)
def test_nested_struct():
cdef = """
typedef struct {
int x;
} foo;
typedef struct {
foo y;
} bar;
"""
cts = parse_source(cdef)
bar = cts.gettype('bar')
assert isinstance(bar, lltype.Struct)
hash(bar) # bar is hashable
def test_const():
cdef = """
typedef struct {
const char * const foo;
} bar;
"""
cts = parse_source(cdef)
assert cts.definitions['bar'].c_foo == rffi.CONST_CCHARP != rffi.CCHARP
def test_gettype():
decl = """
typedef ssize_t Py_ssize_t;
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
Py_ssize_t ob_pypy_link; \
typedef struct {
PyObject_HEAD
double ob_fval;
} TestFloatObject;
"""
cts = parse_source(decl)
assert cts.gettype('Py_ssize_t') == rffi.SSIZE_T
assert cts.gettype('TestFloatObject *').TO.c_ob_refcnt == rffi.SSIZE_T
assert cts.cast('Py_ssize_t', 42) == rffi.cast(rffi.SSIZE_T, 42)
def test_parse_funcdecl():
decl = """
typedef ssize_t Py_ssize_t;
#define PyObject_HEAD \
Py_ssize_t ob_refcnt; \
Py_ssize_t ob_pypy_link; \
typedef struct {
PyObject_HEAD
double ob_fval;
} TestFloatObject;
typedef TestFloatObject* (*func_t)(int, int);
"""
cts = parse_source(decl)
func_decl = cts.parse_func("func_t * some_func(TestFloatObject*)")
assert func_decl.name == 'some_func'
assert func_decl.get_llresult(cts) == cts.gettype('func_t*')
assert func_decl.get_llargs(cts) == [cts.gettype('TestFloatObject *')]
def test_write_func():
from ..api import ApiFunction
from rpython.translator.c.database import LowLevelDatabase
db = LowLevelDatabase()
cdef = """
typedef ssize_t Py_ssize_t;
"""
cts = parse_source(cdef)
cdecl = "Py_ssize_t * some_func(Py_ssize_t*)"
decl = cts.parse_func(cdecl)
api_function = ApiFunction(
decl.get_llargs(cts), decl.get_llresult(cts), lambda space, x: None,
cdecl=decl)
assert (api_function.get_api_decl('some_func', db) ==
"PyAPI_FUNC(Py_ssize_t *) some_func(Py_ssize_t * arg0);")
def test_wchar_t():
cdef = """
typedef struct { wchar_t* x; } test;
"""
cts = parse_source(cdef, headers=['stddef.h'])
obj = lltype.malloc(cts.gettype('test'), flavor='raw')
obj.c_x = cts.cast('wchar_t*', 0)
obj.c_x = lltype.nullptr(rffi.CWCHARP.TO)
lltype.free(obj, flavor='raw')
def test_translate_cast():
cdef = "typedef ssize_t Py_ssize_t;"
cts = parse_source(cdef)
def f():
return cts.cast('Py_ssize_t*', 0)
graph = build_flow(f)
simplify_graph(graph)
assert len(graph.startblock.operations) == 1
op = graph.startblock.operations[0]
assert op.args[0] == const(rffi.cast)
assert op.args[1].value is cts.gettype('Py_ssize_t*')
def test_translate_gettype():
cdef = "typedef ssize_t Py_ssize_t;"
cts = parse_source(cdef)
def f():
return cts.gettype('Py_ssize_t*')
graph = build_flow(f)
simplify_graph(graph)
# Check that the result is constant-folded
assert graph.startblock.operations == []
[link] = graph.startblock.exits
assert link.target is graph.returnblock
assert link.args[0] == const(rffi.CArrayPtr(rffi.SSIZE_T))
|