@@ -101,6 +101,22 @@ TryAddRef(PyObject *cnv, CDataObject *obj)
101101}
102102#endif
103103
104+ static int
105+ is_narrow_int_ffi_type (int type )
106+ {
107+ switch (type ) {
108+ case FFI_TYPE_SINT8 :
109+ case FFI_TYPE_UINT8 :
110+ case FFI_TYPE_SINT16 :
111+ case FFI_TYPE_UINT16 :
112+ case FFI_TYPE_SINT32 :
113+ case FFI_TYPE_UINT32 :
114+ return 1 ;
115+ default :
116+ return 0 ;
117+ }
118+ }
119+
104120/******************************************************************************
105121 *
106122 * Call the python object with all arguments
@@ -222,13 +238,14 @@ static void _CallPythonObject(ctypes_state *st,
222238 if (restype != & ffi_type_void && result ) {
223239 assert (setfunc );
224240
225- #ifdef WORDS_BIGENDIAN
226- /* See the corresponding code in _ctypes_callproc():
227- in callproc.c, around line 1219. */
228- if (restype -> type != FFI_TYPE_FLOAT && restype -> size < sizeof (ffi_arg )) {
229- mem = (char * )mem + sizeof (ffi_arg ) - restype -> size ;
230- }
231- #endif
241+ /* libffi's closure contract requires integral results narrower
242+ than ffi_arg to fill a whole register, sign-extended if signed;
243+ setfunc() only writes restype->size bytes. Cf. _ctypes_callproc()
244+ in callproc.c. */
245+ ffi_arg widened = 0 ;
246+ int narrow = restype -> size < sizeof (ffi_arg ) &&
247+ is_narrow_int_ffi_type (restype -> type );
248+ void * resmem = narrow ? & widened : mem ;
232249
233250 /* keep is an object we have to keep alive so that the result
234251 stays valid. If there is no such object, the setfunc will
@@ -239,7 +256,33 @@ static void _CallPythonObject(ctypes_state *st,
239256 be the result. EXCEPT when restype is py_object - Python
240257 itself knows how to manage the refcount of these objects.
241258 */
242- PyObject * keep = setfunc (mem , result , restype -> size );
259+ PyObject * keep = setfunc (resmem , result , restype -> size );
260+
261+ if (narrow && keep != NULL ) {
262+ switch (restype -> type ) {
263+ case FFI_TYPE_SINT8 :
264+ widened = (ffi_arg )(ffi_sarg )* (int8_t * )& widened ;
265+ break ;
266+ case FFI_TYPE_SINT16 :
267+ widened = (ffi_arg )(ffi_sarg )* (int16_t * )& widened ;
268+ break ;
269+ case FFI_TYPE_SINT32 :
270+ widened = (ffi_arg )(ffi_sarg )* (int32_t * )& widened ;
271+ break ;
272+ case FFI_TYPE_UINT8 :
273+ widened = * (uint8_t * )& widened ;
274+ break ;
275+ case FFI_TYPE_UINT16 :
276+ widened = * (uint16_t * )& widened ;
277+ break ;
278+ case FFI_TYPE_UINT32 :
279+ widened = * (uint32_t * )& widened ;
280+ break ;
281+ default :
282+ break ;
283+ }
284+ memcpy (mem , & widened , sizeof (ffi_arg ));
285+ }
243286
244287 if (keep == NULL ) {
245288 /* Could not convert callback result. */
0 commit comments