def test_string_from_char_array(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("char[]", b"hello.")
p[5] = b'!'
assert ffi.string(p) == b"hello!"
p[6] = b'?'
assert ffi.string(p) == b"hello!?"
p[3] = b'\x00'
assert ffi.string(p) == b"hel"
assert ffi.string(p, 2) == b"he"
py.test.raises(IndexError, "p[7] = b'X'")
#
a = ffi.new("char[]", b"hello\x00world")
assert len(a) == 12
p = ffi.cast("char *", a)
assert ffi.string(p) == b'hello'
python类FFI的实例源码
def test_functionptr_simple(self):
ffi = FFI(backend=self.Backend())
py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
def cb(n):
return n + 1
cb.__qualname__ = 'cb'
p = ffi.callback("int(*)(int)", cb)
res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
assert res == 42 and type(res) is int
res = p(ffi.cast("int", -41))
assert res == -40 and type(res) is int
assert repr(p).startswith(
"<cdata 'int(*)(int)' calling <function cb at 0x")
assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
q = ffi.new("int(**)(int)", p)
assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
SIZE_OF_PTR)
py.test.raises(TypeError, "q(43)")
res = q[0](43)
assert res == 44
q = ffi.cast("int(*)(int)", p)
assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
res = q(45)
assert res == 46
def test_functionptr_intptr_return(self):
ffi = FFI(backend=self.Backend())
def cb():
return ffi.NULL
p = ffi.callback("int*(*)()", cb)
res = p()
assert res == ffi.NULL
int_ptr = ffi.new('int*')
def cb():
return int_ptr
p = ffi.callback("int*(*)()", cb)
res = p()
assert repr(res).startswith("<cdata 'int *' 0x")
assert res == int_ptr
int_array_ptr = ffi.new('int[1]')
def cb():
return int_array_ptr
p = ffi.callback("int*(*)()", cb)
res = p()
assert repr(res).startswith("<cdata 'int *' 0x")
assert res == int_array_ptr
def test_cast_float(self):
ffi = FFI(backend=self.Backend())
a = ffi.cast("float", 12)
assert float(a) == 12.0
a = ffi.cast("float", 12.5)
assert float(a) == 12.5
a = ffi.cast("float", b"A")
assert float(a) == ord("A")
a = ffi.cast("int", 12.9)
assert int(a) == 12
a = ffi.cast("char", 66.9 + 256)
assert ffi.string(a) == b"B"
#
a = ffi.cast("float", ffi.cast("int", 12))
assert float(a) == 12.0
a = ffi.cast("float", ffi.cast("double", 12.5))
assert float(a) == 12.5
a = ffi.cast("float", ffi.cast("char", b"A"))
assert float(a) == ord("A")
a = ffi.cast("int", ffi.cast("double", 12.9))
assert int(a) == 12
a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
assert ffi.string(a) == b"B"
def test_enum(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("enum foo { A0, B0, CC0, D0 };")
assert ffi.string(ffi.cast("enum foo", 0)) == "A0"
assert ffi.string(ffi.cast("enum foo", 2)) == "CC0"
assert ffi.string(ffi.cast("enum foo", 3)) == "D0"
assert ffi.string(ffi.cast("enum foo", 4)) == "4"
ffi.cdef("enum bar { A1, B1=-2, CC1, D1, E1 };")
assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
assert ffi.cast("enum bar", -2) != ffi.cast("enum bar", -2)
assert ffi.cast("enum foo", 0) != ffi.cast("enum bar", 0)
assert ffi.cast("enum bar", 0) != ffi.cast("int", 0)
assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
assert repr(ffi.cast("enum foo", -1)) == ( # enums are unsigned, if
"<cdata 'enum foo' 4294967295>") # they contain no neg value
ffi.cdef("enum baz { A2=0x1000, B2=0x2000 };")
assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
def test_enum_in_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("enum foo { A, B, C, D }; struct bar { enum foo e; };")
s = ffi.new("struct bar *")
s.e = 0
assert s.e == 0
s.e = 3
assert s.e == 3
assert s[0].e == 3
s[0].e = 2
assert s.e == 2
assert s[0].e == 2
s.e = ffi.cast("enum foo", -1)
assert s.e == 4294967295
assert s[0].e == 4294967295
s.e = s.e
py.test.raises(TypeError, "s.e = 'B'")
py.test.raises(TypeError, "s.e = '2'")
py.test.raises(TypeError, "s.e = '#2'")
py.test.raises(TypeError, "s.e = '#7'")
def __init__(self):
# Store these on the class since they should only ever be called once
if _LibUUID._ffi is None or _LibUUID._libuuid is None:
_LibUUID._ffi = FFI()
# These definitions are from uuid.h
_LibUUID._ffi.cdef("""
typedef unsigned char uuid_t[16];
void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);
void uuid_generate_time(uuid_t out);
""")
# By opening the library with dlopen, the compile step is skipped
# dodging a class of errors, since headers aren't needed, just the
# installed library.
_LibUUID._libuuid = _LibUUID._ffi.dlopen(
ctypes.util.find_library("uuid")
)
get_config().logger.debug(
"FastUUID Created - FFI: ({}), LIBUUID: ({})".format(
_LibUUID._ffi,
_LibUUID._libuuid
)
)
# Keeping only one copy of this around does result in
# pretty substantial performance improvements - in the 10,000s of
# messages per second range
self.output = _LibUUID._ffi.new("uuid_t")
def check_lib_python_found(tmpdir):
global _link_error
if _link_error == '?':
ffi = cffi.FFI()
kwds = {}
ffi._apply_embedding_fix(kwds)
ffi.set_source("_test_lib_python_found", "", **kwds)
try:
ffi.compile(tmpdir=tmpdir, verbose=True)
except cffi.VerificationError as e:
_link_error = e
else:
_link_error = None
if _link_error:
py.test.skip(str(_link_error))
def test_multiple_independent_structs(self):
CDEF2 = "struct ab { int x; };"
ffi2 = cffi.FFI(); ffi2.cdef(CDEF2)
outputfilename = recompile(ffi2, "test_multiple_independent_structs",
CDEF2, tmpdir=str(udir))
module = imp.load_dynamic("test_multiple_independent_structs",
outputfilename)
ffi1 = module.ffi
foo1 = ffi1.new("struct ab *", [10])
foo2 = ffi .new("struct ab *", [20, 30])
assert foo1.x == 10
assert foo2.a == 20
assert foo2.b == 30
def test_include_struct_union_enum_typedef(self):
ffi1, CCODE = construction_params
ffi2 = cffi.FFI()
ffi2.include(ffi1)
outputfilename = recompile(ffi2,
"test_include_struct_union_enum_typedef",
CCODE, tmpdir=str(udir))
module = imp.load_dynamic("test_include_struct_union_enum_typedef",
outputfilename)
ffi2 = module.ffi
#
p = ffi2.new("struct nonpacked *", [b'A', -43141])
assert p.a == b'A'
assert p.b == -43141
#
p = ffi.new("union simple_u *", [-52525])
assert p.a == -52525
#
p = ffi.cast("enum foq", 2)
assert ffi.string(p) == "cffiCC0"
assert ffi2.sizeof("char[cffiCC0]") == 2
#
p = ffi.new("anon_foo_t *", [-52526])
assert p.a == -52526
p = ffi.new("named_foo_p", [-52527])
assert p.a == -52527
def test_emit_c_code(self):
ffi = cffi.FFI()
ffi.set_source("foobar", "??")
c_file = str(udir.join('test_emit_c_code'))
ffi.emit_c_code(c_file)
assert os.path.isfile(c_file)
def test_function():
import _cffi_backend
from re_python_pysrc import ffi
lib = ffi.dlopen(extmod)
assert lib.add42(-10) == 32
assert type(lib.add42) is _cffi_backend.FFI.CData
def test_function_with_varargs():
import _cffi_backend
from re_python_pysrc import ffi
lib = ffi.dlopen(extmod, 0)
assert lib.add43(45, ffi.cast("int", -5)) == 45
assert type(lib.add43) is _cffi_backend.FFI.CData
def test_check_version():
import _cffi_backend
e = py.test.raises(ImportError, _cffi_backend.FFI,
"foobar", _version=0x2594)
assert str(e.value).startswith(
"cffi out-of-line Python module 'foobar' has unknown version")
def test_partial_enum():
ffi = FFI()
ffi.cdef("enum foo { A, B, ... };")
ffi.set_source('test_partial_enum', None)
py.test.raises(VerificationMissing, ffi.emit_python_code,
str(tmpdir.join('test_partial_enum.py')))
def test_abi_emit_python_code_2(self):
ffi = cffi.FFI()
ffi.set_source("package_name_1.mymod", None)
py.test.raises(IOError, ffi.emit_python_code, 'unexisting/xyz.py')
def test_abi_emit_python_code_3(self):
ffi = cffi.FFI()
ffi.set_source("package_name_1.mymod", None)
ffi.emit_python_code(str(self.udir.join('xyt.py')))
self.check_produced_files({'xyt.py': None})
def test_abi_compile_1(self):
ffi = cffi.FFI()
ffi.set_source("mod_name_in_package.mymod", None)
x = ffi.compile()
self.check_produced_files({'mod_name_in_package': {'mymod.py': None}})
assert x == os.path.join('.', 'mod_name_in_package', 'mymod.py')
def test_abi_compile_2(self):
ffi = cffi.FFI()
ffi.set_source("mod_name_in_package.mymod", None)
x = ffi.compile('build2')
self.check_produced_files({'build2': {
'mod_name_in_package': {'mymod.py': None}}})
assert x == os.path.join('build2', 'mod_name_in_package', 'mymod.py')
def test_abi_compile_3(self):
ffi = cffi.FFI()
ffi.set_source("mod_name_in_package.mymod", None)
tmpdir = str(self.udir.join('build3'))
x = ffi.compile(tmpdir)
self.check_produced_files({'build3': {
'mod_name_in_package': {'mymod.py': None}}})
assert x == os.path.join(tmpdir, 'mod_name_in_package', 'mymod.py')