Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions Lib/_osx_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ def get_platform_osx(_config_vars, osname, release, machine):

if len(archs) == 1:
machine = archs[0]
elif archs == ('arm64', 'x86_64'):
machine = 'universal2'
elif archs == ('i386', 'ppc'):
machine = 'fat'
elif archs == ('i386', 'x86_64'):
Expand Down
14 changes: 13 additions & 1 deletion Lib/ctypes/macholib/dyld.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,19 @@ def dyld_find(name, executable_path=None, env=None):
dyld_executable_path_search(name, executable_path),
dyld_default_search(name, env),
), env):
if os.path.isfile(path):

# on macOS 11 system libraries are in a shared library
# cache, not in the regular place in the filesystem.
# There still are symlinks (libz.dylib -> libz.1.dylib),
# but the target of the symlink no longer is there.
#
# There shouldn't be 3th-party libraries in these
# system locations
if path.startswith("/System/") and os.path.islink(path):
return path
elif path.startswith("/usr/lib/") and os.path.islink(path):
return path
elif os.path.isfile(path):
return path
raise ValueError("dylib %s could not be found" % (name,))

Expand Down
1 change: 1 addition & 0 deletions Lib/test/test_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ def test_from_format(self):
c_char_p)

PyBytes_FromFormat = pythonapi.PyBytes_FromFormat
PyBytes_FromFormat.argtypes = (c_char_p,)
PyBytes_FromFormat.restype = py_object

# basic tests
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2513,11 +2513,13 @@ class CAPITest(unittest.TestCase):
def test_from_format(self):
import_helper.import_module('ctypes')
from ctypes import (
c_char_p,
pythonapi, py_object, sizeof,
c_int, c_long, c_longlong, c_ssize_t,
c_uint, c_ulong, c_ulonglong, c_size_t, c_void_p)
name = "PyUnicode_FromFormat"
_PyUnicode_FromFormat = getattr(pythonapi, name)
_PyUnicode_FromFormat.argtypes = (c_char_p,)
_PyUnicode_FromFormat.restype = py_object

def PyUnicode_FromFormat(format, *args):
Expand Down
12 changes: 8 additions & 4 deletions Mac/Tools/pythonw.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)
size_t count;
cpu_type_t cpu_types[1];
short flags = 0;
#ifdef __LP64__
int ch;
#endif

if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
err(2, "posix_spawnattr_int");
Expand All @@ -119,10 +116,16 @@ setup_spawnattr(posix_spawnattr_t* spawnattr)

#elif defined(__ppc__)
cpu_types[0] = CPU_TYPE_POWERPC;

#elif defined(__i386__)
cpu_types[0] = CPU_TYPE_X86;

#elif defined(__arm64__)
cpu_types[0] = CPU_TYPE_ARM64;

#else
# error "Unknown CPU"

#endif

if (posix_spawnattr_setbinpref_np(spawnattr, count,
Expand Down Expand Up @@ -220,7 +223,8 @@ main(int argc, char **argv) {
/* We're weak-linking to posix-spawnv to ensure that
* an executable build on 10.5 can work on 10.4.
*/
if (posix_spawn != NULL) {

if (&posix_spawn != NULL) {
posix_spawnattr_t spawnattr = NULL;

setup_spawnattr(&spawnattr);
Expand Down
39 changes: 31 additions & 8 deletions Modules/_ctypes/callbacks.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "Python.h"
#include "frameobject.h"

#include <stdbool.h>

#include <ffi.h>
#ifdef MS_WIN32
#include <windows.h>
Expand All @@ -18,7 +20,7 @@ CThunkObject_dealloc(PyObject *myself)
Py_XDECREF(self->callable);
Py_XDECREF(self->restype);
if (self->pcl_write)
ffi_closure_free(self->pcl_write);
Py_ffi_closure_free(self->pcl_write);
PyObject_GC_Del(self);
}

Expand Down Expand Up @@ -361,8 +363,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,

assert(CThunk_CheckExact((PyObject *)p));

p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
&p->pcl_exec);
p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
if (p->pcl_write == NULL) {
PyErr_NoMemory();
goto error;
Expand Down Expand Up @@ -408,13 +409,35 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
"ffi_prep_cif failed with %d", result);
goto error;
}
#if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
#if HAVE_FFI_PREP_CLOSURE_LOC
# if USING_APPLE_OS_LIBFFI
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# else
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME true
# endif
if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) {
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
p,
p->pcl_exec);
} else
#endif
{
#if USING_APPLE_OS_LIBFFI && defined(__arm64__)
PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
goto error;
#else
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
p,
p->pcl_exec);
#ifdef MACOSX
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);

#ifdef MACOSX
#pragma clang diagnostic pop
#endif

#endif
}
if (result != FFI_OK) {
PyErr_Format(PyExc_RuntimeError,
"ffi_prep_closure failed with %d", result);
Expand Down
72 changes: 60 additions & 12 deletions Modules/_ctypes/callproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#include "Python.h"
#include "structmember.h" // PyMemberDef

#include <stdbool.h>

#ifdef MS_WIN32
#include <windows.h>
#include <tchar.h>
Expand Down Expand Up @@ -812,7 +814,8 @@ static int _call_function_pointer(int flags,
ffi_type **atypes,
ffi_type *restype,
void *resmem,
int argcount)
int argcount,
int argtypecount)
{
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
PyObject *error_object = NULL;
Expand All @@ -835,14 +838,60 @@ static int _call_function_pointer(int flags,
if ((flags & FUNCFLAG_CDECL) == 0)
cc = FFI_STDCALL;
#endif
if (FFI_OK != ffi_prep_cif(&cif,
cc,
argcount,
restype,
atypes)) {
PyErr_SetString(PyExc_RuntimeError,
"ffi_prep_cif failed");
return -1;

# if USING_APPLE_OS_LIBFFI
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
# elif HAVE_FFI_PREP_CIF_VAR
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true
# else
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false
# endif

/* Even on Apple-arm64 the calling convention for variadic functions conincides
* with the standard calling convention in the case that the function called
* only with its fixed arguments. Thus, we do not need a special flag to be
* set on variadic functions. We treat a function as variadic if it is called
* with a nonzero number of variadic arguments */
bool is_variadic = (argtypecount != 0 && argcount > argtypecount);
(void) is_variadic;

#if defined(__APPLE__) && defined(__arm64__)
if (is_variadic) {
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
} else {
PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing");
return -1;
}
}
#endif

#if HAVE_FFI_PREP_CIF_VAR
if (is_variadic) {
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) {
if (FFI_OK != ffi_prep_cif_var(&cif,
cc,
argtypecount,
argcount,
restype,
atypes)) {
PyErr_SetString(PyExc_RuntimeError,
"ffi_prep_cif_var failed");
return -1;
}
}
} else
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will fail for variadic functions on Mac OS 10.14 and below, because it will not call either ffi_prep_cif_var nor ffi_prep_cif

{
if (FFI_OK != ffi_prep_cif(&cif,
cc,
argcount,
restype,
atypes)) {
PyErr_SetString(PyExc_RuntimeError,
"ffi_prep_cif failed");
return -1;
}
}

if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
Expand Down Expand Up @@ -1212,9 +1261,8 @@ PyObject *_ctypes_callproc(PPROC pProc,

if (-1 == _call_function_pointer(flags, pProc, avalues, atypes,
rtype, resbuf,
Py_SAFE_DOWNCAST(argcount,
Py_ssize_t,
int)))
Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int),
Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int)))
goto cleanup;

#ifdef WORDS_BIGENDIAN
Expand Down
8 changes: 8 additions & 0 deletions Modules/_ctypes/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,14 @@ PyObject *_ctypes_get_errobj(int **pspace);
extern PyObject *ComError;
#endif

#if USING_MALLOC_CLOSURE_DOT_C
void Py_ffi_closure_free(void *p);
void *Py_ffi_closure_alloc(size_t size, void** codeloc);
#else
#define Py_ffi_closure_free ffi_closure_free
#define Py_ffi_closure_alloc ffi_closure_alloc
#endif

/*
Local Variables:
compile-command: "python setup.py -q build install --home ~"
Expand Down
15 changes: 13 additions & 2 deletions Modules/_ctypes/malloc_closure.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,27 @@ static void more_core(void)
/******************************************************************/

/* put the item back into the free list */
void ffi_closure_free(void *p)
void Py_ffi_closure_free(void *p)
{
#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
ffi_closure_free(p);
return;
}
#endif
ITEM *item = (ITEM *)p;
item->next = free_list;
free_list = item;
}

/* return one item from the free list, allocating more if needed */
void *ffi_closure_alloc(size_t ignored, void** codeloc)
void *Py_ffi_closure_alloc(size_t size, void** codeloc)
{
#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
return ffi_closure_alloc(size, codeloc);
}
#endif
ITEM *item;
if (!free_list)
more_core();
Expand Down
20 changes: 14 additions & 6 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -1509,8 +1509,8 @@ Optional Packages:
specify the kind of universal binary that should be
created. this option is only valid when
--enable-universalsdk is set; options are:
("32-bit", "64-bit", "3-way", "intel", "intel-32",
"intel-64", or "all") see Mac/README.rst
("universal2", "32-bit", "64-bit", "3-way", "intel",
"intel-32", "intel-64", or "all") see Mac/README.rst
--with-framework-name=FRAMEWORK
specify the name for the python framework on macOS
only valid when --enable-framework is set. see
Expand Down Expand Up @@ -6945,7 +6945,7 @@ fi



# The -arch flags for universal builds on OSX
# The -arch flags for universal builds on macOS
UNIVERSAL_ARCH_FLAGS=


Expand Down Expand Up @@ -7472,6 +7472,11 @@ $as_echo "$CC" >&6; }
LIPO_32BIT_FLAGS="-extract ppc7400 -extract i386"
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
universal2)
UNIVERSAL_ARCH_FLAGS="-arch arm64 -arch x86_64"
LIPO_32BIT_FLAGS=""
ARCH_RUN_32BIT="true"
;;
intel)
UNIVERSAL_ARCH_FLAGS="-arch i386 -arch x86_64"
LIPO_32BIT_FLAGS="-extract i386"
Expand All @@ -7493,7 +7498,7 @@ $as_echo "$CC" >&6; }
ARCH_RUN_32BIT="/usr/bin/arch -i386 -ppc"
;;
*)
as_fn_error $? "proper usage is --with-universal-arch=32-bit|64-bit|all|intel|3-way" "$LINENO" 5
as_fn_error $? "proper usage is --with-universal-arch=universal2|32-bit|64-bit|all|intel|3-way" "$LINENO" 5
;;
esac

Expand Down Expand Up @@ -9322,7 +9327,7 @@ fi
MACOSX_DEFAULT_ARCH="ppc"
;;
*)
as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
;;
esac
else
Expand All @@ -9332,9 +9337,12 @@ fi
;;
ppc)
MACOSX_DEFAULT_ARCH="ppc64"
;;
arm64)
MACOSX_DEFAULT_ARCH="arm64"
;;
*)
as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5
as_fn_error $? "Unexpected output of 'arch' on macOS" "$LINENO" 5
;;
esac

Expand Down
Loading