cffi-1.5.2/ 0000775 0001750 0001750 00000000000 12657646372 012676 5 ustar arigo arigo 0000000 0000000 cffi-1.5.2/setup.py 0000664 0001750 0001750 00000015663 12657646311 014414 0 ustar arigo arigo 0000000 0000000 import sys, os
import subprocess
import errno
sources = ['c/_cffi_backend.c']
libraries = ['ffi']
include_dirs = ['/usr/include/ffi',
'/usr/include/libffi'] # may be changed by pkg-config
define_macros = []
library_dirs = []
extra_compile_args = []
extra_link_args = []
def _ask_pkg_config(resultlist, option, result_prefix='', sysroot=False):
pkg_config = os.environ.get('PKG_CONFIG','pkg-config')
try:
p = subprocess.Popen([pkg_config, option, 'libffi'],
stdout=subprocess.PIPE)
except OSError as e:
if e.errno not in [errno.ENOENT, errno.EACCES]:
raise
else:
t = p.stdout.read().decode().strip()
p.stdout.close()
if p.wait() == 0:
res = t.split()
# '-I/usr/...' -> '/usr/...'
for x in res:
assert x.startswith(result_prefix)
res = [x[len(result_prefix):] for x in res]
#print 'PKG_CONFIG:', option, res
#
sysroot = sysroot and os.environ.get('PKG_CONFIG_SYSROOT_DIR', '')
if sysroot:
# old versions of pkg-config don't support this env var,
# so here we emulate its effect if needed
res = [path if path.startswith(sysroot)
else sysroot + path
for path in res]
#
resultlist[:] = res
def no_working_compiler_found():
sys.stderr.write("""
No working compiler found, or bogus compiler options
passed to the compiler from Python's distutils module.
See the error messages above.
(If they are about -mno-fused-madd and you are on OS/X 10.8,
see http://stackoverflow.com/questions/22313407/ .)\n""")
sys.exit(1)
def ask_supports_thread():
from distutils.core import Distribution
from distutils.sysconfig import get_config_vars
get_config_vars() # workaround for a bug of distutils, e.g. on OS/X
config = Distribution().get_command_obj('config')
ok = config.try_compile('__thread int some_threadlocal_variable_42;')
if ok:
define_macros.append(('USE__THREAD', None))
else:
ok1 = config.try_compile('int some_regular_variable_42;')
if not ok1:
no_working_compiler_found()
sys.stderr.write("Note: will not use '__thread' in the C code\n")
sys.stderr.write("The above error message can be safely ignored\n")
def use_pkg_config():
if sys.platform == 'darwin' and os.path.exists('/usr/local/bin/brew'):
use_homebrew_for_libffi()
_ask_pkg_config(include_dirs, '--cflags-only-I', '-I', sysroot=True)
_ask_pkg_config(extra_compile_args, '--cflags-only-other')
_ask_pkg_config(library_dirs, '--libs-only-L', '-L', sysroot=True)
_ask_pkg_config(extra_link_args, '--libs-only-other')
_ask_pkg_config(libraries, '--libs-only-l', '-l')
def use_homebrew_for_libffi():
# We can build by setting:
# PKG_CONFIG_PATH = $(brew --prefix libffi)/lib/pkgconfig
with os.popen('brew --prefix libffi') as brew_prefix_cmd:
prefix = brew_prefix_cmd.read().strip()
pkgconfig = os.path.join(prefix, 'lib', 'pkgconfig')
os.environ['PKG_CONFIG_PATH'] = (
os.environ.get('PKG_CONFIG_PATH', '') + ':' + pkgconfig)
if sys.platform == 'win32':
COMPILE_LIBFFI = 'c/libffi_msvc' # from the CPython distribution
else:
COMPILE_LIBFFI = None
if COMPILE_LIBFFI:
assert os.path.isdir(COMPILE_LIBFFI), "directory not found!"
include_dirs[:] = [COMPILE_LIBFFI]
libraries[:] = []
_filenames = [filename.lower() for filename in os.listdir(COMPILE_LIBFFI)]
_filenames = [filename for filename in _filenames
if filename.endswith('.c')]
if sys.maxsize > 2**32:
# 64-bit: unlist win32.c, and add instead win64.obj. If the obj
# happens to get outdated at some point in the future, you need to
# rebuild it manually from win64.asm.
_filenames.remove('win32.c')
extra_link_args.append(os.path.join(COMPILE_LIBFFI, 'win64.obj'))
sources.extend(os.path.join(COMPILE_LIBFFI, filename)
for filename in _filenames)
else:
use_pkg_config()
ask_supports_thread()
if 'freebsd' in sys.platform:
include_dirs.append('/usr/local/include')
if __name__ == '__main__':
from setuptools import setup, Distribution, Extension
class CFFIDistribution(Distribution):
def has_ext_modules(self):
# Event if we don't have extension modules (e.g. on PyPy) we want to
# claim that we do so that wheels get properly tagged as Python
# specific. (thanks dstufft!)
return True
# On PyPy, cffi is preinstalled and it is not possible, at least for now,
# to install a different version. We work around it by making the setup()
# arguments mostly empty in this case.
cpython = ('_cffi_backend' not in sys.builtin_module_names)
setup(
name='cffi',
description='Foreign Function Interface for Python calling C code.',
long_description="""
CFFI
====
Foreign Function Interface for Python calling C code.
Please see the `Documentation `_.
Contact
-------
`Mailing list `_
""",
version='1.5.2',
packages=['cffi'] if cpython else [],
package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h',
'_embedding.h']}
if cpython else {},
zip_safe=False,
url='http://cffi.readthedocs.org',
author='Armin Rigo, Maciej Fijalkowski',
author_email='python-cffi@googlegroups.com',
license='MIT',
distclass=CFFIDistribution,
ext_modules=[Extension(
name='_cffi_backend',
include_dirs=include_dirs,
sources=sources,
libraries=libraries,
define_macros=define_macros,
library_dirs=library_dirs,
extra_compile_args=extra_compile_args,
extra_link_args=extra_link_args,
)] if cpython else [],
install_requires=[
'pycparser',
] if cpython else [],
entry_points = {
"distutils.setup_keywords": [
"cffi_modules = cffi.setuptools_ext:cffi_modules",
],
} if cpython else {},
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
],
)
cffi-1.5.2/cffi.egg-info/ 0000775 0001750 0001750 00000000000 12657646372 015277 5 ustar arigo arigo 0000000 0000000 cffi-1.5.2/cffi.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12657646372 017525 0 ustar arigo arigo 0000000 0000000
cffi-1.5.2/cffi.egg-info/top_level.txt 0000664 0001750 0001750 00000000023 12657646372 020024 0 ustar arigo arigo 0000000 0000000 _cffi_backend
cffi
cffi-1.5.2/cffi.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12657646372 021345 0 ustar arigo arigo 0000000 0000000
cffi-1.5.2/cffi.egg-info/entry_points.txt 0000664 0001750 0001750 00000000114 12657646372 020571 0 ustar arigo arigo 0000000 0000000 [distutils.setup_keywords]
cffi_modules = cffi.setuptools_ext:cffi_modules
cffi-1.5.2/cffi.egg-info/SOURCES.txt 0000664 0001750 0001750 00000011224 12657646372 017163 0 ustar arigo arigo 0000000 0000000 AUTHORS
LICENSE
MANIFEST.in
setup.py
setup_base.py
c/_cffi_backend.c
c/call_python.c
c/cdlopen.c
c/cffi1_module.c
c/cglob.c
c/commontypes.c
c/ffi_obj.c
c/file_emulator.h
c/lib_obj.c
c/malloc_closure.h
c/minibuffer.h
c/misc_thread_common.h
c/misc_thread_posix.h
c/misc_win32.h
c/parse_c_type.c
c/realize_c_type.c
c/test_c.py
c/wchar_helper.h
c/libffi_msvc/ffi.c
c/libffi_msvc/ffi.h
c/libffi_msvc/ffi_common.h
c/libffi_msvc/fficonfig.h
c/libffi_msvc/ffitarget.h
c/libffi_msvc/prep_cif.c
c/libffi_msvc/types.c
c/libffi_msvc/win32.c
c/libffi_msvc/win64.asm
c/libffi_msvc/win64.obj
cffi/__init__.py
cffi/_cffi_include.h
cffi/_embedding.h
cffi/api.py
cffi/backend_ctypes.py
cffi/cffi_opcode.py
cffi/commontypes.py
cffi/cparser.py
cffi/ffiplatform.py
cffi/gc_weakref.py
cffi/lock.py
cffi/model.py
cffi/parse_c_type.h
cffi/recompiler.py
cffi/setuptools_ext.py
cffi/vengine_cpy.py
cffi/vengine_gen.py
cffi/verifier.py
cffi.egg-info/PKG-INFO
cffi.egg-info/SOURCES.txt
cffi.egg-info/dependency_links.txt
cffi.egg-info/entry_points.txt
cffi.egg-info/not-zip-safe
cffi.egg-info/requires.txt
cffi.egg-info/top_level.txt
demo/_curses.py
demo/_curses_build.py
demo/_curses_setup.py
demo/api.py
demo/bsdopendirtype.py
demo/bsdopendirtype_build.py
demo/bsdopendirtype_setup.py
demo/btrfs-snap.py
demo/cffi-cocoa.py
demo/embedding.py
demo/embedding_test.c
demo/extern_python.py
demo/extern_python_varargs.py
demo/fastcsv.py
demo/gmp.py
demo/gmp_build.py
demo/manual.c
demo/manual2.py
demo/pwuid.py
demo/pwuid_build.py
demo/py.cleanup
demo/pyobj.py
demo/readdir.py
demo/readdir2.py
demo/readdir2_build.py
demo/readdir2_setup.py
demo/readdir_build.py
demo/readdir_ctypes.py
demo/readdir_setup.py
demo/recopendirtype.py
demo/recopendirtype_build.py
demo/setup.py
demo/setup_manual.py
demo/winclipboard.py
demo/winclipboard_build.py
demo/xclient.py
demo/xclient_build.py
doc/Makefile
doc/make.bat
doc/misc/design.rst
doc/misc/grant-cffi-1.0.rst
doc/misc/parse_c_type.rst
doc/source/cdef.rst
doc/source/conf.py
doc/source/embedding.rst
doc/source/index.rst
doc/source/installation.rst
doc/source/overview.rst
doc/source/using.rst
doc/source/whatsnew.rst
testing/__init__.py
testing/support.py
testing/udir.py
testing/cffi0/__init__.py
testing/cffi0/backend_tests.py
testing/cffi0/callback_in_thread.py
testing/cffi0/test_cdata.py
testing/cffi0/test_ctypes.py
testing/cffi0/test_ffi_backend.py
testing/cffi0/test_function.py
testing/cffi0/test_model.py
testing/cffi0/test_ownlib.py
testing/cffi0/test_parsing.py
testing/cffi0/test_platform.py
testing/cffi0/test_unicode_literals.py
testing/cffi0/test_verify.py
testing/cffi0/test_verify2.py
testing/cffi0/test_version.py
testing/cffi0/test_vgen.py
testing/cffi0/test_vgen2.py
testing/cffi0/test_zdistutils.py
testing/cffi0/test_zintegration.py
testing/cffi0/snippets/distutils_module/setup.py
testing/cffi0/snippets/distutils_module/snip_basic_verify.py
testing/cffi0/snippets/distutils_package_1/setup.py
testing/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py
testing/cffi0/snippets/distutils_package_2/setup.py
testing/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py
testing/cffi0/snippets/infrastructure/setup.py
testing/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py
testing/cffi0/snippets/setuptools_module/setup.py
testing/cffi0/snippets/setuptools_module/snip_setuptools_verify.py
testing/cffi0/snippets/setuptools_package_1/setup.py
testing/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py
testing/cffi0/snippets/setuptools_package_2/setup.py
testing/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py
testing/cffi1/__init__.py
testing/cffi1/test_cffi_binary.py
testing/cffi1/test_commontypes.py
testing/cffi1/test_dlopen.py
testing/cffi1/test_dlopen_unicode_literals.py
testing/cffi1/test_ffi_obj.py
testing/cffi1/test_new_ffi_1.py
testing/cffi1/test_parse_c_type.py
testing/cffi1/test_re_python.py
testing/cffi1/test_realize_c_type.py
testing/cffi1/test_recompiler.py
testing/cffi1/test_unicode_literals.py
testing/cffi1/test_verify1.py
testing/cffi1/test_zdist.py
testing/embedding/__init__.py
testing/embedding/add1-test.c
testing/embedding/add1.py
testing/embedding/add2-test.c
testing/embedding/add2.py
testing/embedding/add3.py
testing/embedding/add_recursive-test.c
testing/embedding/add_recursive.py
testing/embedding/perf-test.c
testing/embedding/perf.py
testing/embedding/test_basic.py
testing/embedding/test_performance.py
testing/embedding/test_recursive.py
testing/embedding/test_thread.py
testing/embedding/test_tlocal.py
testing/embedding/thread-test.h
testing/embedding/thread1-test.c
testing/embedding/thread2-test.c
testing/embedding/thread3-test.c
testing/embedding/tlocal-test.c
testing/embedding/tlocal.py cffi-1.5.2/cffi.egg-info/requires.txt 0000664 0001750 0001750 00000000012 12657646372 017670 0 ustar arigo arigo 0000000 0000000 pycparser
cffi-1.5.2/cffi.egg-info/PKG-INFO 0000664 0001750 0001750 00000002131 12657646372 016371 0 ustar arigo arigo 0000000 0000000 Metadata-Version: 1.1
Name: cffi
Version: 1.5.2
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
Author-email: python-cffi@googlegroups.com
License: MIT
Description:
CFFI
====
Foreign Function Interface for Python calling C code.
Please see the `Documentation `_.
Contact
-------
`Mailing list `_
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
cffi-1.5.2/testing/ 0000775 0001750 0001750 00000000000 12657646372 014353 5 ustar arigo arigo 0000000 0000000 cffi-1.5.2/testing/cffi0/ 0000775 0001750 0001750 00000000000 12657646372 015342 5 ustar arigo arigo 0000000 0000000 cffi-1.5.2/testing/cffi0/test_zintegration.py 0000664 0001750 0001750 00000012531 12657646311 021463 0 ustar arigo arigo 0000000 0000000 import py, os, sys, shutil
import subprocess
from testing.udir import udir
if sys.platform == 'win32':
py.test.skip('snippets do not run on win32')
if sys.version_info < (2, 7):
py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
' in a non-2.6-friendly way')
def create_venv(name):
tmpdir = udir.join(name)
try:
subprocess.check_call(['virtualenv', '--distribute',
'-p', os.path.abspath(sys.executable),
str(tmpdir)])
except OSError as e:
py.test.skip("Cannot execute virtualenv: %s" % (e,))
site_packages = None
for dirpath, dirnames, filenames in os.walk(str(tmpdir)):
if os.path.basename(dirpath) == 'site-packages':
site_packages = dirpath
break
paths = ""
if site_packages:
try:
from cffi import _pycparser
modules = ('cffi', '_cffi_backend')
except ImportError:
modules = ('cffi', '_cffi_backend', 'pycparser')
try:
import ply
except ImportError:
pass
else:
modules += ('ply',) # needed for older versions of pycparser
paths = []
for module in modules:
target = __import__(module, None, None, [])
if not hasattr(target, '__file__'): # for _cffi_backend on pypy
continue
src = os.path.abspath(target.__file__)
for end in ['__init__.pyc', '__init__.pyo', '__init__.py']:
if src.lower().endswith(end):
src = src[:-len(end)-1]
break
paths.append(os.path.dirname(src))
paths = os.pathsep.join(paths)
return tmpdir, paths
SNIPPET_DIR = py.path.local(__file__).join('..', 'snippets')
def really_run_setup_and_program(dirname, venv_dir_and_paths, python_snippet):
venv_dir, paths = venv_dir_and_paths
def remove(dir):
dir = str(SNIPPET_DIR.join(dirname, dir))
shutil.rmtree(dir, ignore_errors=True)
remove('build')
remove('__pycache__')
for basedir in os.listdir(str(SNIPPET_DIR.join(dirname))):
remove(os.path.join(basedir, '__pycache__'))
olddir = os.getcwd()
python_f = udir.join('x.py')
python_f.write(py.code.Source(python_snippet))
try:
os.chdir(str(SNIPPET_DIR.join(dirname)))
if os.name == 'nt':
bindir = 'Scripts'
else:
bindir = 'bin'
vp = str(venv_dir.join(bindir).join('python'))
env = os.environ.copy()
env['PYTHONPATH'] = paths
subprocess.check_call((vp, 'setup.py', 'clean'), env=env)
subprocess.check_call((vp, 'setup.py', 'install'), env=env)
subprocess.check_call((vp, str(python_f)), env=env)
finally:
os.chdir(olddir)
def run_setup_and_program(dirname, python_snippet):
venv_dir = create_venv(dirname + '-cpy')
really_run_setup_and_program(dirname, venv_dir, python_snippet)
#
sys._force_generic_engine_ = True
try:
venv_dir = create_venv(dirname + '-gen')
really_run_setup_and_program(dirname, venv_dir, python_snippet)
finally:
del sys._force_generic_engine_
# the two files lextab.py and yacctab.py are created by not-correctly-
# installed versions of pycparser.
assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py')))
assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py')))
class TestZIntegration(object):
def teardown_class(self):
if udir.isdir():
udir.remove(ignore_errors=True)
udir.ensure(dir=1)
def test_infrastructure(self):
run_setup_and_program('infrastructure', '''
import snip_infrastructure
assert snip_infrastructure.func() == 42
''')
def test_distutils_module(self):
run_setup_and_program("distutils_module", '''
import snip_basic_verify
p = snip_basic_verify.C.getpwuid(0)
assert snip_basic_verify.ffi.string(p.pw_name) == b"root"
''')
def test_distutils_package_1(self):
run_setup_and_program("distutils_package_1", '''
import snip_basic_verify1
p = snip_basic_verify1.C.getpwuid(0)
assert snip_basic_verify1.ffi.string(p.pw_name) == b"root"
''')
def test_distutils_package_2(self):
run_setup_and_program("distutils_package_2", '''
import snip_basic_verify2
p = snip_basic_verify2.C.getpwuid(0)
assert snip_basic_verify2.ffi.string(p.pw_name) == b"root"
''')
def test_setuptools_module(self):
run_setup_and_program("setuptools_module", '''
import snip_setuptools_verify
p = snip_setuptools_verify.C.getpwuid(0)
assert snip_setuptools_verify.ffi.string(p.pw_name) == b"root"
''')
def test_setuptools_package_1(self):
run_setup_and_program("setuptools_package_1", '''
import snip_setuptools_verify1
p = snip_setuptools_verify1.C.getpwuid(0)
assert snip_setuptools_verify1.ffi.string(p.pw_name) == b"root"
''')
def test_setuptools_package_2(self):
run_setup_and_program("setuptools_package_2", '''
import snip_setuptools_verify2
p = snip_setuptools_verify2.C.getpwuid(0)
assert snip_setuptools_verify2.ffi.string(p.pw_name) == b"root"
''')
cffi-1.5.2/testing/cffi0/test_function.py 0000664 0001750 0001750 00000040757 12657646311 020606 0 ustar arigo arigo 0000000 0000000 import py
from cffi import FFI, CDefError
import math, os, sys
import ctypes.util
from cffi.backend_ctypes import CTypesBackend
from testing.udir import udir
from testing.support import FdWriteCapture
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
lib_m = 'm'
if sys.platform == 'win32':
#there is a small chance this fails on Mingw via environ $CC
import distutils.ccompiler
if distutils.ccompiler.get_default_compiler() == 'msvc':
lib_m = 'msvcrt'
class TestFunction(object):
Backend = CTypesBackend
def test_sin(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
double sin(double x);
""")
m = ffi.dlopen(lib_m)
x = m.sin(1.23)
assert x == math.sin(1.23)
def test_sinf(self):
if sys.platform == 'win32':
py.test.skip("no sinf found in the Windows stdlib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
float sinf(float x);
""")
m = ffi.dlopen(lib_m)
x = m.sinf(1.23)
assert type(x) is float
assert x != math.sin(1.23) # rounding effects
assert abs(x - math.sin(1.23)) < 1E-6
def test_sin_no_return_value(self):
# check that 'void'-returning functions work too
ffi = FFI(backend=self.Backend())
ffi.cdef("""
void sin(double x);
""")
m = ffi.dlopen(lib_m)
x = m.sin(1.23)
assert x is None
def test_dlopen_filename(self):
path = ctypes.util.find_library(lib_m)
if not path:
py.test.skip("%s not found" % lib_m)
ffi = FFI(backend=self.Backend())
ffi.cdef("""
double cos(double x);
""")
m = ffi.dlopen(path)
x = m.cos(1.23)
assert x == math.cos(1.23)
m = ffi.dlopen(os.path.basename(path))
x = m.cos(1.23)
assert x == math.cos(1.23)
def test_dlopen_flags(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
double cos(double x);
""")
m = ffi.dlopen(lib_m, ffi.RTLD_LAZY | ffi.RTLD_LOCAL)
x = m.cos(1.23)
assert x == math.cos(1.23)
def test_dlopen_constant(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
#define FOOBAR 42
static const float baz = 42.5; /* not visible */
double sin(double x);
""")
m = ffi.dlopen(lib_m)
assert m.FOOBAR == 42
py.test.raises(NotImplementedError, "m.baz")
def test_tlsalloc(self):
if sys.platform != 'win32':
py.test.skip("win32 only")
if self.Backend is CTypesBackend:
py.test.skip("ctypes complains on wrong calling conv")
ffi = FFI(backend=self.Backend())
ffi.cdef("long TlsAlloc(void); int TlsFree(long);")
lib = ffi.dlopen('KERNEL32.DLL')
x = lib.TlsAlloc()
assert x != 0
y = lib.TlsFree(x)
assert y != 0
def test_fputs(self):
if not sys.platform.startswith('linux'):
py.test.skip("probably no symbol 'stderr' in the lib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fputs(const char *, void *);
void *stderr;
""")
ffi.C = ffi.dlopen(None)
ffi.C.fputs # fetch before capturing, for easier debugging
with FdWriteCapture() as fd:
ffi.C.fputs(b"hello\n", ffi.C.stderr)
ffi.C.fputs(b" world\n", ffi.C.stderr)
res = fd.getvalue()
assert res == b'hello\n world\n'
def test_fputs_without_const(self):
if not sys.platform.startswith('linux'):
py.test.skip("probably no symbol 'stderr' in the lib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fputs(char *, void *);
void *stderr;
""")
ffi.C = ffi.dlopen(None)
ffi.C.fputs # fetch before capturing, for easier debugging
with FdWriteCapture() as fd:
ffi.C.fputs(b"hello\n", ffi.C.stderr)
ffi.C.fputs(b" world\n", ffi.C.stderr)
res = fd.getvalue()
assert res == b'hello\n world\n'
def test_vararg(self):
if not sys.platform.startswith('linux'):
py.test.skip("probably no symbol 'stderr' in the lib")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int fprintf(void *, const char *format, ...);
void *stderr;
""")
ffi.C = ffi.dlopen(None)
with FdWriteCapture() as fd:
ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n")
ffi.C.fprintf(ffi.C.stderr,
b"hello, %s!\n", ffi.new("char[]", b"world"))
ffi.C.fprintf(ffi.C.stderr,
ffi.new("char[]", b"hello, %s!\n"),
ffi.new("char[]", b"world2"))
ffi.C.fprintf(ffi.C.stderr,
b"hello int %d long %ld long long %lld\n",
ffi.cast("int", 42),
ffi.cast("long", 84),
ffi.cast("long long", 168))
ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL)
res = fd.getvalue()
assert res == (b"hello with no arguments\n"
b"hello, world!\n"
b"hello, world2!\n"
b"hello int 42 long 84 long long 168\n"
b"hello (nil)\n")
def test_must_specify_type_of_vararg(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int printf(const char *format, ...);
""")
ffi.C = ffi.dlopen(None)
e = py.test.raises(TypeError, ffi.C.printf, b"hello %d\n", 42)
assert str(e.value) == ("argument 2 passed in the variadic part "
"needs to be a cdata object (got int)")
def test_function_has_a_c_type(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int puts(const char *);
""")
ffi.C = ffi.dlopen(None)
fptr = ffi.C.puts
assert ffi.typeof(fptr) == ffi.typeof("int(*)(const char*)")
if self.Backend is CTypesBackend:
assert repr(fptr).startswith("" % (cb,)
res = fptr(b"Hello")
assert res == 42
#
if not sys.platform.startswith('linux'):
py.test.skip("probably no symbol 'stderr' in the lib")
ffi.cdef("""
int fputs(const char *, void *);
void *stderr;
""")
ffi.C = ffi.dlopen(None)
fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
assert fptr == ffi.C.fputs
assert repr(fptr).startswith(" lambda (closure) -> container -> callback
return callback
class Data(object):
pass
ffi = FFI(backend=self.Backend())
data = Data()
callback = make_callback(data)
wr = weakref.ref(data)
del callback, data
for i in range(3):
if wr() is not None:
import gc; gc.collect()
assert wr() is None # 'data' does not leak
def test_windows_stdcall(self):
if sys.platform != 'win32':
py.test.skip("Windows-only test")
if self.Backend is CTypesBackend:
py.test.skip("not with the ctypes backend")
ffi = FFI(backend=self.Backend())
ffi.cdef("""
BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
""")
m = ffi.dlopen("Kernel32.dll")
p_freq = ffi.new("LONGLONG *")
res = m.QueryPerformanceFrequency(p_freq)
assert res != 0
assert p_freq[0] != 0
def test_explicit_cdecl_stdcall(self):
if sys.platform != 'win32':
py.test.skip("Windows-only test")
if self.Backend is CTypesBackend:
py.test.skip("not with the ctypes backend")
win64 = (sys.maxsize > 2**32)
#
ffi = FFI(backend=self.Backend())
ffi.cdef("""
BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
""")
m = ffi.dlopen("Kernel32.dll")
tp = ffi.typeof(m.QueryPerformanceFrequency)
assert str(tp) == ""
#
ffi = FFI(backend=self.Backend())
ffi.cdef("""
BOOL __cdecl QueryPerformanceFrequency(LONGLONG *lpFrequency);
""")
m = ffi.dlopen("Kernel32.dll")
tpc = ffi.typeof(m.QueryPerformanceFrequency)
assert tpc is tp
#
ffi = FFI(backend=self.Backend())
ffi.cdef("""
BOOL WINAPI QueryPerformanceFrequency(LONGLONG *lpFrequency);
""")
m = ffi.dlopen("Kernel32.dll")
tps = ffi.typeof(m.QueryPerformanceFrequency)
if win64:
assert tps is tpc
else:
assert tps is not tpc
assert str(tps) == ""
#
ffi = FFI(backend=self.Backend())
ffi.cdef("typedef int (__cdecl *fnc_t)(int);")
ffi.cdef("typedef int (__stdcall *fns_t)(int);")
tpc = ffi.typeof("fnc_t")
tps = ffi.typeof("fns_t")
assert str(tpc) == ""
if win64:
assert tps is tpc
else:
assert str(tps) == ""
#
fnc = ffi.cast("fnc_t", 0)
fns = ffi.cast("fns_t", 0)
ffi.new("fnc_t[]", [fnc])
if not win64:
py.test.raises(TypeError, ffi.new, "fnc_t[]", [fns])
py.test.raises(TypeError, ffi.new, "fns_t[]", [fnc])
ffi.new("fns_t[]", [fns])
def test_stdcall_only_on_windows(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("double __stdcall sin(double x);") # stdcall ignored
m = ffi.dlopen(lib_m)
if (sys.platform == 'win32' and sys.maxsize < 2**32 and
self.Backend is not CTypesBackend):
assert "double(__stdcall *)(double)" in str(ffi.typeof(m.sin))
else:
assert "double(*)(double)" in str(ffi.typeof(m.sin))
x = m.sin(1.23)
assert x == math.sin(1.23)
def test_dir_on_dlopen_lib(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
typedef enum { MYE1, MYE2 } myenum_t;
double myfunc(double);
double myvar;
const double myconst;
#define MYFOO 42
""")
m = ffi.dlopen(lib_m)
assert dir(m) == ['MYE1', 'MYE2', 'MYFOO', 'myconst', 'myfunc', 'myvar']
cffi-1.5.2/testing/cffi0/test_verify2.py 0000664 0001750 0001750 00000000474 12657646311 020337 0 ustar arigo arigo 0000000 0000000 from .test_verify import *
# This test file runs normally after test_verify. We only clean up the .c
# sources, to check that it also works when we have only the .so. The
# tests should run much faster than test_verify.
def setup_module():
import cffi.verifier
cffi.verifier.cleanup_tmpdir(keep_so=True)
cffi-1.5.2/testing/cffi0/test_parsing.py 0000664 0001750 0001750 00000034775 12657646311 020427 0 ustar arigo arigo 0000000 0000000 import py, sys, re
from cffi import FFI, FFIError, CDefError, VerificationError
class FakeBackend(object):
def nonstandard_integer_types(self):
return {}
def sizeof(self, name):
return 1
def load_library(self, name, flags):
if sys.platform == 'win32':
assert name is None or "msvcr" in name
else:
assert name is None or "libc" in name or "libm" in name
return FakeLibrary()
def new_function_type(self, args, result, has_varargs):
args = [arg.cdecl for arg in args]
result = result.cdecl
return FakeType(
'' % (', '.join(args), result, has_varargs))
def new_primitive_type(self, name):
assert name == name.lower()
return FakeType('<%s>' % name)
def new_pointer_type(self, itemtype):
return FakeType('' % (itemtype,))
def new_struct_type(self, name):
return FakeStruct(name)
def complete_struct_or_union(self, s, fields, tp=None,
totalsize=-1, totalalignment=-1, sflags=0):
assert isinstance(s, FakeStruct)
s.fields = fields
def new_array_type(self, ptrtype, length):
return FakeType('' % (ptrtype, length))
def new_void_type(self):
return FakeType("")
def cast(self, x, y):
return 'casted!'
def _get_types(self):
return "CData", "CType"
class FakeType(object):
def __init__(self, cdecl):
self.cdecl = cdecl
def __str__(self):
return self.cdecl
class FakeStruct(object):
def __init__(self, name):
self.name = name
def __str__(self):
return ', '.join([str(y) + str(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 = str(BType)
self.name = name
lib_m = "m"
if sys.platform == 'win32':
#there is a small chance this fails on Mingw via environ $CC
import distutils.ccompiler
if distutils.ccompiler.get_default_compiler() == 'msvc':
lib_m = 'msvcrt'
def test_simple():
ffi = FFI(backend=FakeBackend())
ffi.cdef("double sin(double x);")
m = ffi.dlopen(lib_m)
func = m.sin # should be a callable on real backends
assert func.name == 'sin'
assert func.BType == '), , False>'
def test_pipe():
ffi = FFI(backend=FakeBackend())
ffi.cdef("int pipe(int pipefd[2]);")
C = ffi.dlopen(None)
func = C.pipe
assert func.name == 'pipe'
assert func.BType == '>), , False>'
def test_vararg():
ffi = FFI(backend=FakeBackend())
ffi.cdef("short foo(int, ...);")
C = ffi.dlopen(None)
func = C.foo
assert func.name == 'foo'
assert func.BType == '), , True>'
def test_no_args():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
int foo(void);
""")
C = ffi.dlopen(None)
assert C.foo.BType == ', False>'
def test_typedef():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef unsigned int UInt;
typedef UInt UIntReally;
UInt foo(void);
""")
C = ffi.dlopen(None)
assert str(ffi.typeof("UIntReally")) == ''
assert C.foo.BType == ', 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[]);
""")
C = ffi.dlopen(None)
assert str(ffi.typeof("foo_t")) == 'a, b'
assert str(ffi.typeof("foo_p")) == 'a, b>'
assert C.foo.BType == ('a, b>>), , False>')
def test_typedef_array_convert_array_to_pointer():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
typedef int (*fn_t)(int[5]);
""")
with ffi._lock:
type = ffi._parser.parse_type("fn_t")
BType = ffi._get_cached_btype(type)
assert str(BType) == '>), , False>'
def test_remove_comments():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
double /*comment here*/ sin // blah blah
/* multi-
line-
//comment */ (
// foo
double // bar /* <- ignored, because it's in a comment itself
x, double/*several*//*comment*/y) /*on the same line*/
;
""")
m = ffi.dlopen(lib_m)
func = m.sin
assert func.name == 'sin'
assert func.BType == ', ), , False>'
def test_remove_line_continuation_comments():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
double // blah \\
more comments
x(void);
double // blah\\\\
y(void);
double // blah\\ \
etc
z(void);
""")
m = ffi.dlopen(lib_m)
m.x
m.y
m.z
def test_line_continuation_in_defines():
ffi = FFI(backend=FakeBackend())
ffi.cdef("""
#define ABC\\
42
#define BCD \\
43
""")
m = ffi.dlopen(lib_m)
assert m.ABC == 42
assert m.BCD == 43
def test_define_not_supported_for_now():
ffi = FFI(backend=FakeBackend())
e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"')
assert str(e.value) == (
'only supports one of the following syntax:\n'
' #define FOO ... (literally dot-dot-dot)\n'
' #define FOO NUMBER (with NUMBER an integer'
' constant, decimal/hex/octal)\n'
'got:\n'
' #define FOO "blah"')
def test_unnamed_struct():
ffi = FFI(backend=FakeBackend())
ffi.cdef("typedef struct { int x; } foo_t;\n"
"typedef struct { int y; } *bar_p;\n")
assert 'typedef foo_t' in ffi._parser._declarations
assert 'typedef bar_p' in ffi._parser._declarations
assert 'anonymous foo_t' in ffi._parser._declarations
type_foo = ffi._parser.parse_type("foo_t")
type_bar = ffi._parser.parse_type("bar_p").totype
assert repr(type_foo) == ""
assert repr(type_bar) == ""
py.test.raises(VerificationError, type_bar.get_c_name)
assert type_foo.get_c_name() == "foo_t"
def test_override():
ffi = FFI(backend=FakeBackend())
C = ffi.dlopen(None)
ffi.cdef("int foo(void);")
py.test.raises(FFIError, ffi.cdef, "long foo(void);")
assert C.foo.BType == ', False>'
ffi.cdef("long foo(void);", override=True)
assert C.foo.BType == ', False>'
def test_cannot_have_only_variadic_part():
# this checks that we get a sensible error if we try "int foo(...);"
ffi = FFI()
e = py.test.raises(CDefError, ffi.cdef, "int foo(...);")
assert str(e.value) == \
"foo: a function with only '(...)' as argument is not correct C"
def test_parse_error():
ffi = FFI()
e = py.test.raises(CDefError, ffi.cdef, " x y z ")
assert re.match(r'cannot parse "x y z"\n:\d+:', str(e.value))
def test_cannot_declare_enum_later():
ffi = FFI()
e = py.test.raises(NotImplementedError, ffi.cdef,
"typedef enum foo_e foo_t; enum foo_e { AA, BB };")
assert str(e.value) == (
"enum foo_e: the '{}' declaration should appear on the "
"first time the enum is mentioned, not later")
def test_unknown_name():
ffi = FFI()
e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown", 0)
assert str(e.value) == "unknown identifier 'foobarbazunknown'"
e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown*", 0)
assert str(e.value).startswith('cannot parse "foobarbazunknown*"')
e = py.test.raises(CDefError, ffi.cast, "int(*)(foobarbazunknown)", 0)
assert str(e.value).startswith('cannot parse "int(*)(foobarbazunknown)"')
def test_redefine_common_type():
prefix = "" if sys.version_info < (3,) else "b"
ffi = FFI()
ffi.cdef("typedef char FILE;")
assert repr(ffi.cast("FILE", 123)) == "" % prefix
ffi.cdef("typedef char int32_t;")
assert repr(ffi.cast("int32_t", 123)) == "" % prefix
ffi = FFI()
ffi.cdef("typedef int bool, *FILE;")
assert repr(ffi.cast("bool", 123)) == ""
assert re.match(r"",
repr(ffi.cast("FILE", 123)))
ffi = FFI()
ffi.cdef("typedef bool (*fn_t)(bool, bool);") # "bool," but within "( )"
def test_bool():
ffi = FFI()
ffi.cdef("void f(bool);")
#
ffi = FFI()
ffi.cdef("typedef _Bool bool; void f(bool);")
def test_unknown_argument_type():
ffi = FFI()
e = py.test.raises(CDefError, ffi.cdef, "void f(foobarbazzz);")
assert str(e.value) == ("f arg 1: unknown type 'foobarbazzz' (if you meant"
" to use the old C syntax of giving untyped"
" arguments, it is not supported)")
def test_void_renamed_as_only_arg():
ffi = FFI()
ffi.cdef("typedef void void_t1;"
"typedef void_t1 void_t;"
"typedef int (*func_t)(void_t);")
assert ffi.typeof("func_t").args == ()
def test_WPARAM_on_windows():
if sys.platform != 'win32':
py.test.skip("Only for Windows")
ffi = FFI()
ffi.cdef("void f(WPARAM);")
#
# WPARAM -> UINT_PTR -> unsigned 32/64-bit integer
ffi = FFI()
value = int(ffi.cast("WPARAM", -42))
assert value == sys.maxsize * 2 - 40
def test__is_constant_globalvar():
for input, expected_output in [
("int a;", False),
("const int a;", True),
("int *a;", False),
("const int *a;", False),
("int const *a;", False),
("int *const a;", True),
("int a[5];", False),
("const int a[5];", False),
("int *a[5];", False),
("const int *a[5];", False),
("int const *a[5];", False),
("int *const a[5];", False),
("int a[5][6];", False),
("const int a[5][6];", False),
]:
ffi = FFI()
ffi.cdef(input)
declarations = ffi._parser._declarations
assert ('constant a' in declarations) == expected_output
assert ('variable a' in declarations) == (not expected_output)
def test_restrict():
from cffi import model
for input, expected_output in [
("int a;", False),
("restrict int a;", True),
("int *a;", False),
]:
ffi = FFI()
ffi.cdef(input)
tp, quals = ffi._parser._declarations['variable a']
assert bool(quals & model.Q_RESTRICT) == expected_output
def test_different_const_funcptr_types():
lst = []
for input in [
"int(*)(int *a)",
"int(*)(int const *a)",
"int(*)(int * const a)",
"int(*)(int const a[])"]:
ffi = FFI(backend=FakeBackend())
lst.append(ffi._parser.parse_type(input))
assert lst[0] != lst[1]
assert lst[0] == lst[2]
assert lst[1] == lst[3]
def test_const_pointer_to_pointer():
from cffi import model
ffi = FFI(backend=FakeBackend())
#
tp, qual = ffi._parser.parse_type_and_quals("char * * (* const)")
assert (str(tp), qual) == ("", model.Q_CONST)
tp, qual = ffi._parser.parse_type_and_quals("char * (* const (*))")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("char (* const (* (*)))")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("char const * * *")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
assert (str(tp), qual) == ("", 0)
#
tp, qual = ffi._parser.parse_type_and_quals("char * * * const const")
assert (str(tp), qual) == ("", model.Q_CONST)
tp, qual = ffi._parser.parse_type_and_quals("char * * volatile *")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("char * volatile restrict * *")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("char const volatile * * *")
assert (str(tp), qual) == ("", 0)
tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
assert (str(tp), qual) == ("", 0)
#
tp, qual = ffi._parser.parse_type_and_quals(
"int(char*const*, short****const*)")
assert (str(tp), qual) == (
"", 0)
tp, qual = ffi._parser.parse_type_and_quals(
"char*const*(short*const****)")
assert (str(tp), qual) == (
"", 0)
def test_enum():
ffi = FFI()
ffi.cdef("""
enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1};
""")
C = ffi.dlopen(None)
assert C.POS == 1
assert C.TWO == 2
assert C.NIL == 0
assert C.NEG == -1
def test_stdcall():
ffi = FFI()
tp = ffi.typeof("int(*)(int __stdcall x(int),"
" long (__cdecl*y)(void),"
" short(WINAPI *z)(short))")
if sys.platform == 'win32' and sys.maxsize < 2**32:
stdcall = '__stdcall '
else:
stdcall = ''
assert str(tp) == (
"" % (stdcall, stdcall))
def test_extern_python():
ffi = FFI()
ffi.cdef("""
int bok(int, int);
extern "Python" int foobar(int, int);
int baz(int, int);
""")
assert sorted(ffi._parser._declarations) == [
'extern_python foobar', 'function baz', 'function bok']
assert (ffi._parser._declarations['function bok'] ==
ffi._parser._declarations['extern_python foobar'] ==
ffi._parser._declarations['function baz'])
def test_extern_python_group():
ffi = FFI()
ffi.cdef("""
int bok(int);
extern "Python" {int foobar(int, int);int bzrrr(int);}
int baz(int, int);
""")
assert sorted(ffi._parser._declarations) == [
'extern_python bzrrr', 'extern_python foobar',
'function baz', 'function bok']
assert (ffi._parser._declarations['function baz'] ==
ffi._parser._declarations['extern_python foobar'] !=
ffi._parser._declarations['function bok'] ==
ffi._parser._declarations['extern_python bzrrr'])
cffi-1.5.2/testing/cffi0/backend_tests.py 0000664 0001750 0001750 00000205023 12657646311 020520 0 ustar arigo arigo 0000000 0000000 import py
import platform
import sys, ctypes
from cffi import FFI, CDefError, FFIError, VerificationMissing
from testing.support import *
SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
class BackendTests:
def test_integer_ranges(self):
ffi = FFI(backend=self.Backend())
for (c_type, size) in [('char', 1),
('short', 2),
('short int', 2),
('', 4),
('int', 4),
('long', SIZE_OF_LONG),
('long int', SIZE_OF_LONG),
('long long', 8),
('long long int', 8),
]:
for unsigned in [None, False, True]:
c_decl = {None: '',
False: 'signed ',
True: 'unsigned '}[unsigned] + c_type
if c_decl == 'char' or c_decl == '':
continue
self._test_int_type(ffi, c_decl, size, unsigned)
def test_fixedsize_int(self):
ffi = FFI(backend=self.Backend())
for size in [1, 2, 4, 8]:
self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
def _test_int_type(self, ffi, c_decl, size, unsigned):
if unsigned:
min = 0
max = (1 << (8*size)) - 1
else:
min = -(1 << (8*size-1))
max = (1 << (8*size-1)) - 1
min = int(min)
max = int(max)
p = ffi.cast(c_decl, min)
assert p != min # no __eq__(int)
assert bool(p) is True
assert int(p) == min
p = ffi.cast(c_decl, max)
assert int(p) == max
p = ffi.cast(c_decl, long(max))
assert int(p) == max
q = ffi.cast(c_decl, min - 1)
assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
q = ffi.cast(c_decl, long(min - 1))
assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
assert q != p
assert int(q) == int(p)
assert hash(q) != hash(p) # unlikely
c_decl_ptr = '%s *' % c_decl
py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
assert ffi.new(c_decl_ptr, min)[0] == min
assert ffi.new(c_decl_ptr, max)[0] == max
assert ffi.new(c_decl_ptr, long(min))[0] == min
assert ffi.new(c_decl_ptr, long(max))[0] == max
def test_new_unsupported_type(self):
ffi = FFI(backend=self.Backend())
e = py.test.raises(TypeError, ffi.new, "int")
assert str(e.value) == "expected a pointer or array ctype, got 'int'"
def test_new_single_integer(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int *") # similar to ffi.new("int[1]")
assert p[0] == 0
p[0] = -123
assert p[0] == -123
p = ffi.new("int *", -42)
assert p[0] == -42
assert repr(p) == "" % SIZE_OF_INT
def test_new_array_no_arg(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int[10]")
# the object was zero-initialized:
for i in range(10):
assert p[i] == 0
def test_array_indexing(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int[10]")
p[0] = 42
p[9] = 43
assert p[0] == 42
assert p[9] == 43
py.test.raises(IndexError, "p[10]")
py.test.raises(IndexError, "p[10] = 44")
py.test.raises(IndexError, "p[-1]")
py.test.raises(IndexError, "p[-1] = 44")
def test_new_array_args(self):
ffi = FFI(backend=self.Backend())
# this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
# then here we must enclose the items in a list
p = ffi.new("int[5]", [10, 20, 30, 40, 50])
assert p[0] == 10
assert p[1] == 20
assert p[2] == 30
assert p[3] == 40
assert p[4] == 50
p = ffi.new("int[4]", [25])
assert p[0] == 25
assert p[1] == 0 # follow C convention rather than LuaJIT's
assert p[2] == 0
assert p[3] == 0
p = ffi.new("int[4]", [ffi.cast("int", -5)])
assert p[0] == -5
assert repr(p) == "" % (4*SIZE_OF_INT)
def test_new_array_varsize(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int[]", 10) # a single integer is the length
assert p[9] == 0
py.test.raises(IndexError, "p[10]")
#
py.test.raises(TypeError, ffi.new, "int[]")
#
p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
assert p[0] == -6
assert p[1] == -7
py.test.raises(IndexError, "p[2]")
assert repr(p) == "" % (2*SIZE_OF_INT)
#
p = ffi.new("int[]", 0)
py.test.raises(IndexError, "p[0]")
py.test.raises(ValueError, ffi.new, "int[]", -1)
assert repr(p) == ""
def test_pointer_init(self):
ffi = FFI(backend=self.Backend())
n = ffi.new("int *", 24)
a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
for i in range(10):
if i not in (2, 3):
assert a[i] == ffi.NULL
assert a[2] == a[3] == n
def test_cannot_cast(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("short int[10]")
e = py.test.raises(TypeError, ffi.new, "long int **", a)
msg = str(e.value)
assert "'short[10]'" in msg and "'long *'" in msg
def test_new_pointer_to_array(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("int[4]", [100, 102, 104, 106])
p = ffi.new("int **", a)
assert p[0] == ffi.cast("int *", a)
assert p[0][2] == 104
p = ffi.cast("int *", a)
assert p[0] == 100
assert p[1] == 102
assert p[2] == 104
assert p[3] == 106
# keepalive: a
def test_pointer_direct(self):
ffi = FFI(backend=self.Backend())
p = ffi.cast("int*", 0)
assert p is not None
assert bool(p) is False
assert p == ffi.cast("int*", 0)
assert p != None
assert repr(p) == ""
a = ffi.new("int[]", [123, 456])
p = ffi.cast("int*", a)
assert bool(p) is True
assert p == ffi.cast("int*", a)
assert p != ffi.cast("int*", 0)
assert p[0] == 123
assert p[1] == 456
def test_repr(self):
typerepr = self.TypeRepr
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { short a, b, c; };")
p = ffi.cast("short unsigned int", 0)
assert repr(p) == ""
assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
p = ffi.cast("unsigned short int", 0)
assert repr(p) == ""
assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
p = ffi.cast("int*", 0)
assert repr(p) == ""
assert repr(ffi.typeof(p)) == typerepr % "int *"
#
p = ffi.new("int*")
assert repr(p) == "" % SIZE_OF_INT
assert repr(ffi.typeof(p)) == typerepr % "int *"
p = ffi.new("int**")
assert repr(p) == "" % SIZE_OF_PTR
assert repr(ffi.typeof(p)) == typerepr % "int * *"
p = ffi.new("int [2]")
assert repr(p) == "" % (2*SIZE_OF_INT)
assert repr(ffi.typeof(p)) == typerepr % "int[2]"
p = ffi.new("int*[2][3]")
assert repr(p) == "" % (
6*SIZE_OF_PTR)
assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
p = ffi.new("struct foo *")
assert repr(p) == "" % (
3*SIZE_OF_SHORT)
assert repr(ffi.typeof(p)) == typerepr % "struct foo *"
#
q = ffi.cast("short", -123)
assert repr(q) == ""
assert repr(ffi.typeof(q)) == typerepr % "short"
p = ffi.new("int*")
q = ffi.cast("short*", p)
assert repr(q).startswith(" 2:
assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
else:
py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
assert ffi.new("wchar_t*")[0] == u+'\x00'
assert int(ffi.cast("wchar_t", 300)) == 300
assert bool(ffi.cast("wchar_t", 0))
py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
#
p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
assert len(p) == 3
assert p[0] == u+'a'
assert p[1] == u+'b' and type(p[1]) is unicode
assert p[2] == u+'\u1234'
p[0] = u+'x'
assert p[0] == u+'x' and type(p[0]) is unicode
p[1] = u+'\u1357'
assert p[1] == u+'\u1357'
p = ffi.new("wchar_t[]", u+"abcd")
assert len(p) == 5
assert p[4] == u+'\x00'
p = ffi.new("wchar_t[]", u+"a\u1234b")
assert len(p) == 4
assert p[1] == u+'\u1234'
#
p = ffi.new("wchar_t[]", u+'\U00023456')
if SIZE_OF_WCHAR == 2:
assert sys.maxunicode == 0xffff
assert len(p) == 3
assert p[0] == u+'\ud84d'
assert p[1] == u+'\udc56'
assert p[2] == u+'\x00'
else:
assert len(p) == 2
assert p[0] == u+'\U00023456'
assert p[1] == u+'\x00'
#
p = ffi.new("wchar_t[4]", u+"ab")
assert len(p) == 4
assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
p = ffi.new("wchar_t[2]", u+"ab")
assert len(p) == 2
assert [p[i] for i in range(2)] == [u+'a', u+'b']
py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
def test_none_as_null_doesnt_work(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int*[1]")
assert p[0] is not None
assert p[0] != None
assert p[0] == ffi.NULL
assert repr(p[0]) == ""
#
n = ffi.new("int*", 99)
p = ffi.new("int*[]", [n])
assert p[0][0] == 99
py.test.raises(TypeError, "p[0] = None")
p[0] = ffi.NULL
assert p[0] == ffi.NULL
def test_float(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("float[]", [-2, -2.5])
assert p[0] == -2.0
assert p[1] == -2.5
p[1] += 17.75
assert p[1] == 15.25
#
p = ffi.new("float*", 15.75)
assert p[0] == 15.75
py.test.raises(TypeError, int, p)
py.test.raises(TypeError, float, p)
p[0] = 0.0
assert bool(p) is True
#
p = ffi.new("float*", 1.1)
f = p[0]
assert f != 1.1 # because of rounding effect
assert abs(f - 1.1) < 1E-7
#
INF = 1E200 * 1E200
assert 1E200 != INF
p[0] = 1E200
assert p[0] == INF # infinite, not enough precision
def test_struct_simple(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a; short b, c; };")
s = ffi.new("struct foo*")
assert s.a == s.b == s.c == 0
s.b = -23
assert s.b == -23
py.test.raises(OverflowError, "s.b = 32768")
#
s = ffi.new("struct foo*", [-2, -3])
assert s.a == -2
assert s.b == -3
assert s.c == 0
py.test.raises((AttributeError, TypeError), "del s.a")
assert repr(s) == "" % (
SIZE_OF_INT + 2 * SIZE_OF_SHORT)
#
py.test.raises(ValueError, ffi.new, "struct foo*", [1, 2, 3, 4])
def test_constructor_struct_from_dict(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a; short b, c; };")
s = ffi.new("struct foo*", {'b': 123, 'c': 456})
assert s.a == 0
assert s.b == 123
assert s.c == 456
py.test.raises(KeyError, ffi.new, "struct foo*", {'d': 456})
def test_struct_pointer(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a; short b, c; };")
s = ffi.new("struct foo*")
assert s[0].a == s[0].b == s[0].c == 0
s[0].b = -23
assert s[0].b == s.b == -23
py.test.raises(OverflowError, "s[0].b = -32769")
py.test.raises(IndexError, "s[1]")
def test_struct_opaque(self):
ffi = FFI(backend=self.Backend())
py.test.raises(TypeError, ffi.new, "struct baz*")
p = ffi.new("struct baz **") # this works
assert p[0] == ffi.NULL
def test_pointer_to_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a; short b, c; };")
s = ffi.new("struct foo *")
s.a = -42
assert s[0].a == -42
p = ffi.new("struct foo **", s)
assert p[0].a == -42
assert p[0][0].a == -42
p[0].a = -43
assert s.a == -43
assert s[0].a == -43
p[0][0].a = -44
assert s.a == -44
assert s[0].a == -44
s.a = -45
assert p[0].a == -45
assert p[0][0].a == -45
s[0].a = -46
assert p[0].a == -46
assert p[0][0].a == -46
def test_constructor_struct_of_array(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a[2]; char b[3]; };")
s = ffi.new("struct foo *", [[10, 11], [b'a', b'b', b'c']])
assert s.a[1] == 11
assert s.b[2] == b'c'
s.b[1] = b'X'
assert s.b[0] == b'a'
assert s.b[1] == b'X'
assert s.b[2] == b'c'
def test_recursive_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int value; struct foo *next; };")
s = ffi.new("struct foo*")
t = ffi.new("struct foo*")
s.value = 123
s.next = t
t.value = 456
assert s.value == 123
assert s.next.value == 456
def test_union_simple(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("union foo { int a; short b, c; };")
u = ffi.new("union foo*")
assert u.a == u.b == u.c == 0
u.b = -23
assert u.b == -23
assert u.a != 0
py.test.raises(OverflowError, "u.b = 32768")
#
u = ffi.new("union foo*", [-2])
assert u.a == -2
py.test.raises((AttributeError, TypeError), "del u.a")
assert repr(u) == "" % SIZE_OF_INT
def test_union_opaque(self):
ffi = FFI(backend=self.Backend())
py.test.raises(TypeError, ffi.new, "union baz *")
u = ffi.new("union baz **") # this works
assert u[0] == ffi.NULL
def test_union_initializer(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("union foo { char a; int b; };")
py.test.raises(TypeError, ffi.new, "union foo*", b'A')
py.test.raises(TypeError, ffi.new, "union foo*", 5)
py.test.raises(ValueError, ffi.new, "union foo*", [b'A', 5])
u = ffi.new("union foo*", [b'A'])
assert u.a == b'A'
py.test.raises(TypeError, ffi.new, "union foo*", [1005])
u = ffi.new("union foo*", {'b': 12345})
assert u.b == 12345
u = ffi.new("union foo*", [])
assert u.a == b'\x00'
assert u.b == 0
def test_sizeof_type(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
struct foo { int a; short b, c, d; };
union foo { int a; short b, c, d; };
""")
for c_type, expected_size in [
('char', 1),
('unsigned int', 4),
('char *', SIZE_OF_PTR),
('int[5]', 20),
('struct foo', 12),
('union foo', 4),
]:
size = ffi.sizeof(c_type)
assert size == expected_size, (size, expected_size, ctype)
def test_sizeof_cdata(self):
ffi = FFI(backend=self.Backend())
assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
#
a = ffi.new("int[]", [10, 11, 12, 13, 14])
assert len(a) == 5
assert ffi.sizeof(a) == 5 * SIZE_OF_INT
def test_string_from_char_pointer(self):
ffi = FFI(backend=self.Backend())
x = ffi.new("char*", b"x")
assert str(x) == repr(x)
assert ffi.string(x) == b"x"
assert ffi.string(ffi.new("char*", b"\x00")) == b""
py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
def test_unicode_from_wchar_pointer(self):
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
x = ffi.new("wchar_t*", u+"x")
assert unicode(x) == unicode(repr(x))
assert ffi.string(x) == u+"x"
assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
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'
def test_string_from_wchar_array(self):
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
x = ffi.cast("wchar_t", "x")
assert str(x) == repr(x)
assert ffi.string(x) == u+"x"
#
p = ffi.new("wchar_t[]", u+"hello.")
p[5] = u+'!'
assert ffi.string(p) == u+"hello!"
p[6] = u+'\u04d2'
assert ffi.string(p) == u+"hello!\u04d2"
p[3] = u+'\x00'
assert ffi.string(p) == u+"hel"
assert ffi.string(p, 123) == u+"hel"
py.test.raises(IndexError, "p[7] = u+'X'")
#
a = ffi.new("wchar_t[]", u+"hello\x00world")
assert len(a) == 12
p = ffi.cast("wchar_t *", a)
assert ffi.string(p) == u+'hello'
assert ffi.string(p, 123) == u+'hello'
assert ffi.string(p, 5) == u+'hello'
assert ffi.string(p, 2) == u+'he'
def test_fetch_const_char_p_field(self):
# 'const' is ignored so far
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { const char *name; };")
t = ffi.new("const char[]", b"testing")
s = ffi.new("struct foo*", [t])
assert type(s.name) not in (bytes, str, unicode)
assert ffi.string(s.name) == b"testing"
py.test.raises(TypeError, "s.name = None")
s.name = ffi.NULL
assert s.name == ffi.NULL
def test_fetch_const_wchar_p_field(self):
# 'const' is ignored so far
ffi = FFI(backend=self.Backend())
self.check_wchar_t(ffi)
ffi.cdef("struct foo { const wchar_t *name; };")
t = ffi.new("const wchar_t[]", u+"testing")
s = ffi.new("struct foo*", [t])
assert type(s.name) not in (bytes, str, unicode)
assert ffi.string(s.name) == u+"testing"
s.name = ffi.NULL
assert s.name == ffi.NULL
def test_voidp(self):
ffi = FFI(backend=self.Backend())
py.test.raises(TypeError, ffi.new, "void*")
p = ffi.new("void **")
assert p[0] == ffi.NULL
a = ffi.new("int[]", [10, 11, 12])
p = ffi.new("void **", a)
vp = p[0]
py.test.raises(TypeError, "vp[0]")
py.test.raises(TypeError, ffi.new, "short **", a)
#
ffi.cdef("struct foo { void *p; int *q; short *r; };")
s = ffi.new("struct foo *")
s.p = a # works
s.q = a # works
py.test.raises(TypeError, "s.r = a") # fails
b = ffi.cast("int *", a)
s.p = b # works
s.q = b # works
py.test.raises(TypeError, "s.r = b") # fails
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(
"" % (
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(""
assert repr(ffi.cast("enum foo", -1)) == ( # enums are unsigned, if
"") # 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 test_enum_non_contiguous(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("enum foo { A, B=42, C };")
assert ffi.string(ffi.cast("enum foo", 0)) == "A"
assert ffi.string(ffi.cast("enum foo", 42)) == "B"
assert ffi.string(ffi.cast("enum foo", 43)) == "C"
invalid_value = ffi.cast("enum foo", 2)
assert int(invalid_value) == 2
assert ffi.string(invalid_value) == "2"
def test_enum_char_hex_oct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};")
assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A"
assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B"
assert ffi.string(ffi.cast("enum foo", 16)) == "C"
assert ffi.string(ffi.cast("enum foo", 8)) == "D"
assert ffi.string(ffi.cast("enum foo", -16)) == "E"
assert ffi.string(ffi.cast("enum foo", -8)) == "F"
def test_enum_partial(self):
ffi = FFI(backend=self.Backend())
ffi.cdef(r"enum foo {A, ...}; enum bar { B, C };")
lib = ffi.dlopen(None)
assert lib.B == 0
py.test.raises(VerificationMissing, getattr, lib, "A")
assert lib.C == 1
def test_array_of_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a, b; };")
s = ffi.new("struct foo[1]")
py.test.raises(AttributeError, 's.b')
py.test.raises(AttributeError, 's.b = 412')
s[0].b = 412
assert s[0].b == 412
py.test.raises(IndexError, 's[1]')
def test_pointer_to_array(self):
ffi = FFI(backend=self.Backend())
p = ffi.new("int(**)[5]")
assert repr(p) == "" % SIZE_OF_PTR
def test_iterate_array(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("char[]", b"hello")
assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
#
py.test.raises(TypeError, iter, ffi.cast("char *", a))
py.test.raises(TypeError, list, ffi.cast("char *", a))
py.test.raises(TypeError, iter, ffi.new("int *"))
py.test.raises(TypeError, list, ffi.new("int *"))
def test_offsetof(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a, b, c; };")
assert ffi.offsetof("struct foo", "a") == 0
assert ffi.offsetof("struct foo", "b") == 4
assert ffi.offsetof("struct foo", "c") == 8
def test_offsetof_nested(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a, b, c; };"
"struct bar { struct foo d, e; };")
assert ffi.offsetof("struct bar", "e") == 12
py.test.raises(KeyError, ffi.offsetof, "struct bar", "e.a")
assert ffi.offsetof("struct bar", "e", "a") == 12
assert ffi.offsetof("struct bar", "e", "b") == 16
assert ffi.offsetof("struct bar", "e", "c") == 20
def test_offsetof_array(self):
ffi = FFI(backend=self.Backend())
assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
ffi.cdef("struct bar { int a, b; int c[99]; };")
assert ffi.offsetof("struct bar", "c") == 2 * ffi.sizeof("int")
assert ffi.offsetof("struct bar", "c", 0) == 2 * ffi.sizeof("int")
assert ffi.offsetof("struct bar", "c", 51) == 53 * ffi.sizeof("int")
def test_alignof(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { char a; short b; char c; };")
assert ffi.alignof("int") == 4
assert ffi.alignof("double") in (4, 8)
assert ffi.alignof("struct foo") == 2
def test_bitfield(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { int a:10, b:20, c:3; };")
assert ffi.sizeof("struct foo") == 8
s = ffi.new("struct foo *")
s.a = 511
py.test.raises(OverflowError, "s.a = 512")
py.test.raises(OverflowError, "s[0].a = 512")
assert s.a == 511
s.a = -512
py.test.raises(OverflowError, "s.a = -513")
py.test.raises(OverflowError, "s[0].a = -513")
assert s.a == -512
s.c = 3
assert s.c == 3
py.test.raises(OverflowError, "s.c = 4")
py.test.raises(OverflowError, "s[0].c = 4")
s.c = -4
assert s.c == -4
def test_bitfield_enum(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
typedef enum { AA, BB, CC } foo_e;
typedef struct { foo_e f:2; } foo_s;
""")
s = ffi.new("foo_s *")
s.f = 2
assert s.f == 2
def test_anonymous_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("typedef struct { int a; } foo_t;")
ffi.cdef("typedef struct { char b, c; } bar_t;")
f = ffi.new("foo_t *", [12345])
b = ffi.new("bar_t *", [b"B", b"C"])
assert f.a == 12345
assert b.b == b"B"
assert b.c == b"C"
assert repr(b).startswith(" s) is False
assert (p >= s) is True
assert (s < p) is False
assert (s <= p) is True
assert (s == p) is True
assert (s != p) is False
assert (s > p) is False
assert (s >= p) is True
q = p + 1
assert (q < s) is False
assert (q <= s) is False
assert (q == s) is False
assert (q != s) is True
assert (q > s) is True
assert (q >= s) is True
assert (s < q) is True
assert (s <= q) is True
assert (s == q) is False
assert (s != q) is True
assert (s > q) is False
assert (s >= q) is False
assert (q < p) is False
assert (q <= p) is False
assert (q == p) is False
assert (q != p) is True
assert (q > p) is True
assert (q >= p) is True
assert (p < q) is True
assert (p <= q) is True
assert (p == q) is False
assert (p != q) is True
assert (p > q) is False
assert (p >= q) is False
#
assert (None == s) is False
assert (None != s) is True
assert (s == None) is False
assert (s != None) is True
assert (None == q) is False
assert (None != q) is True
assert (q == None) is False
assert (q != None) is True
def test_no_integer_comparison(self):
ffi = FFI(backend=self.Backend())
x = ffi.cast("int", 123)
y = ffi.cast("int", 456)
py.test.raises(TypeError, "x < y")
#
z = ffi.cast("double", 78.9)
py.test.raises(TypeError, "x < z")
py.test.raises(TypeError, "z < y")
def test_ffi_buffer_ptr(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("short *", 100)
try:
b = ffi.buffer(a)
except NotImplementedError as e:
py.test.skip(str(e))
content = b[:]
assert len(content) == len(b) == 2
if sys.byteorder == 'little':
assert content == b'\x64\x00'
assert b[0] == b'\x64'
b[0] = b'\x65'
else:
assert content == b'\x00\x64'
assert b[1] == b'\x64'
b[1] = b'\x65'
assert a[0] == 101
def test_ffi_buffer_array(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("int[]", list(range(100, 110)))
try:
b = ffi.buffer(a)
except NotImplementedError as e:
py.test.skip(str(e))
content = b[:]
if sys.byteorder == 'little':
assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
b[4] = b'\x45'
else:
assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
b[7] = b'\x45'
assert len(content) == 4 * 10
assert a[1] == 0x45
def test_ffi_buffer_ptr_size(self):
ffi = FFI(backend=self.Backend())
a = ffi.new("short *", 0x4243)
try:
b = ffi.buffer(a, 1)
except NotImplementedError as e:
py.test.skip(str(e))
content = b[:]
assert len(content) == 1
if sys.byteorder == 'little':
assert content == b'\x43'
b[0] = b'\x62'
assert a[0] == 0x4262
else:
assert content == b'\x42'
b[0] = b'\x63'
assert a[0] == 0x6343
def test_ffi_buffer_array_size(self):
ffi = FFI(backend=self.Backend())
a1 = ffi.new("int[]", list(range(100, 110)))
a2 = ffi.new("int[]", list(range(100, 115)))
try:
ffi.buffer(a1)
except NotImplementedError as e:
py.test.skip(str(e))
assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
def test_ffi_buffer_with_file(self):
ffi = FFI(backend=self.Backend())
import tempfile, os, array
fd, filename = tempfile.mkstemp()
f = os.fdopen(fd, 'r+b')
a = ffi.new("int[]", list(range(1005)))
try:
ffi.buffer(a, 512)
except NotImplementedError as e:
py.test.skip(str(e))
f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
f.seek(0)
assert f.read() == array.array('i', range(1000)).tostring()
f.seek(0)
b = ffi.new("int[]", 1005)
f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
f.close()
os.unlink(filename)
def test_ffi_buffer_with_io(self):
ffi = FFI(backend=self.Backend())
import io, array
f = io.BytesIO()
a = ffi.new("int[]", list(range(1005)))
try:
ffi.buffer(a, 512)
except NotImplementedError as e:
py.test.skip(str(e))
f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
f.seek(0)
assert f.read() == array.array('i', range(1000)).tostring()
f.seek(0)
b = ffi.new("int[]", 1005)
f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
f.close()
def test_array_in_struct(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo_s { int len; short data[5]; };")
p = ffi.new("struct foo_s *")
p.data[3] = 5
assert p.data[3] == 5
assert repr(p.data).startswith("