86
86
#define DONT_USE_SEH
87
87
#endif
88
88
89
+ #if defined(__APPLE__ ) && __arm64__
90
+ #define HAVE_FFI_PREP_CIF_VAR 1
91
+ #endif
92
+
89
93
#define CTYPES_CAPSULE_NAME_PYMEM "_ctypes pymem"
90
94
91
95
static void pymem_destructor (PyObject * ptr )
@@ -812,7 +816,8 @@ static int _call_function_pointer(int flags,
812
816
ffi_type * * atypes ,
813
817
ffi_type * restype ,
814
818
void * resmem ,
815
- int argcount )
819
+ int argcount ,
820
+ int argtypecount )
816
821
{
817
822
PyThreadState * _save = NULL ; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */
818
823
PyObject * error_object = NULL ;
@@ -835,15 +840,39 @@ static int _call_function_pointer(int flags,
835
840
if ((flags & FUNCFLAG_CDECL ) == 0 )
836
841
cc = FFI_STDCALL ;
837
842
#endif
838
- if (FFI_OK != ffi_prep_cif (& cif ,
839
- cc ,
840
- argcount ,
841
- restype ,
842
- atypes )) {
843
- PyErr_SetString (PyExc_RuntimeError ,
844
- "ffi_prep_cif failed" );
845
- return -1 ;
843
+
844
+ #if HAVE_FFI_PREP_CIF_VAR
845
+ /* Everyone SHOULD set f.variadic=True on variadic function pointers, but
846
+ * lots of existing code will not. If there's at least one arg and more
847
+ * args are passed than are defined in the prototype, then it must be a
848
+ * variadic function. */
849
+ if ((flags & FUNCFLAG_VARIADIC ) ||
850
+ (argtypecount != 0 && argcount > argtypecount ))
851
+ {
852
+ if (FFI_OK != ffi_prep_cif_var (& cif ,
853
+ cc ,
854
+ argtypecount ,
855
+ argcount ,
856
+ restype ,
857
+ atypes )) {
858
+ PyErr_SetString (PyExc_RuntimeError ,
859
+ "ffi_prep_cif_var failed" );
860
+ return -1 ;
861
+ }
862
+ } else {
863
+ #endif
864
+ if (FFI_OK != ffi_prep_cif (& cif ,
865
+ cc ,
866
+ argcount ,
867
+ restype ,
868
+ atypes )) {
869
+ PyErr_SetString (PyExc_RuntimeError ,
870
+ "ffi_prep_cif failed" );
871
+ return -1 ;
872
+ }
873
+ #if HAVE_FFI_PREP_CIF_VAR
846
874
}
875
+ #endif
847
876
848
877
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR )) {
849
878
error_object = _ctypes_get_errobj (& space );
@@ -1212,9 +1241,8 @@ PyObject *_ctypes_callproc(PPROC pProc,
1212
1241
1213
1242
if (-1 == _call_function_pointer (flags , pProc , avalues , atypes ,
1214
1243
rtype , resbuf ,
1215
- Py_SAFE_DOWNCAST (argcount ,
1216
- Py_ssize_t ,
1217
- int )))
1244
+ Py_SAFE_DOWNCAST (argcount , Py_ssize_t , int ),
1245
+ Py_SAFE_DOWNCAST (argtype_count , Py_ssize_t , int )))
1218
1246
goto cleanup ;
1219
1247
1220
1248
#ifdef WORDS_BIGENDIAN
0 commit comments