Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion doc/source/whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ What's New
v2.2.0.dev0
===========

* TBD
* Fixed variadic function calls on Apple platforms when ``_cffi_backend`` is
built against a libffi other than the one provided by the macOS SDK — that
is, the iOS/tvOS/watchOS wheels, or a macOS build using a Homebrew libffi.
(`#265`_).

.. _`#265`: https://github.com/python-cffi/cffi/pull/265

v2.1.0
======
Expand Down
19 changes: 19 additions & 0 deletions src/c/_cffi_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,25 @@
# define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1

#elif defined(__APPLE__)

/* On Apple platforms, but built against a libffi whose headers do not
* define FFI_AVAILABLE_APPLE: not the OS-provided libffi, but e.g. the
* static libffi that iOS/tvOS/watchOS wheels are built against, or a
* Homebrew libffi on macOS. There is no runtime-availability question
* there: whatever the linker resolved is present, so all three functions
* can be used unconditionally. ffi_prep_cif_var() in particular must be
* used: on arm64 Apple platforms variadic arguments are passed on the
* stack, unlike regular arguments, so calling a variadic function through
* a cif prepared with ffi_prep_cif() silently passes garbage.
*/
# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
# define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1
# define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
# define CFFI_CHECK_FFI_PREP_CIF_VAR 1
# define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1

#elif defined(__EMSCRIPTEN__)

# define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
Expand Down
10 changes: 0 additions & 10 deletions src/c/test_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,11 +1233,6 @@ def test_cannot_pass_struct_with_array_of_length_0():
BFunc2 = new_function_type((BInt,), BStruct, False)
pytest.raises(NotImplementedError, cast(BFunc2, 123), 123)

@pytest.mark.xfail(
is_ios,
reason="For an unknown reason f(1, cast(BInt, 42)) returns 36792864",
raises=AssertionError,
)
def test_call_function_9():
BInt = new_primitive_type("int")
BFunc9 = new_function_type((BInt,), BInt, True) # vararg
Expand Down Expand Up @@ -3022,11 +3017,6 @@ def test_string_assignment_to_byte_array():
except ImportError:
pass # win32

@pytest.mark.skipif(
is_ios,
reason="For an unknown reason fscanf() doesn't read anything on 3.14"
" and crashes on 3.13 (that's why it's not an xfail)",
)
def test_FILE():
if sys.platform == "win32":
pytest.skip("testing FILE not implemented")
Expand Down