@@ -146,47 +146,48 @@ static void _CallPythonObject(void *mem,
146
146
int flags ,
147
147
void * * pArgs )
148
148
{
149
- Py_ssize_t i ;
150
- PyObject * result ;
151
- PyObject * arglist = NULL ;
152
- Py_ssize_t nArgs ;
149
+ PyObject * result = NULL ;
150
+ PyObject * * args = NULL ;
151
+ Py_ssize_t i = 0 , j = 0 , nargs = 0 ;
153
152
PyObject * error_object = NULL ;
154
153
int * space ;
155
154
PyGILState_STATE state = PyGILState_Ensure ();
156
155
157
- nArgs = PySequence_Length (converters );
156
+ assert (PyTuple_Check (converters ));
157
+ nargs = PyTuple_GET_SIZE (converters );
158
158
/* Hm. What to return in case of error?
159
159
For COM, 0xFFFFFFFF seems better than 0.
160
160
*/
161
- if (nArgs < 0 ) {
161
+ if (nargs < 0 ) {
162
162
PrintError ("BUG: PySequence_Length" );
163
163
goto Done ;
164
164
}
165
165
166
- arglist = PyTuple_New (nArgs );
167
- if (!arglist ) {
168
- PrintError ("PyTuple_New()" );
169
- goto Done ;
166
+ PyObject * args_stack [CTYPES_MAX_ARGCOUNT ];
167
+ if (nargs <= CTYPES_MAX_ARGCOUNT ) {
168
+ args = args_stack ;
170
169
}
171
- for (i = 0 ; i < nArgs ; ++ i ) {
172
- /* Note: new reference! */
173
- PyObject * cnv = PySequence_GetItem (converters , i );
174
- StgDictObject * dict ;
175
- if (cnv )
176
- dict = PyType_stgdict (cnv );
177
- else {
178
- PrintError ("Getting argument converter %zd\n" , i );
170
+ else {
171
+ args = PyMem_Malloc (nargs * sizeof (PyObject * ));
172
+ if (args == NULL ) {
173
+ PyErr_NoMemory ();
179
174
goto Done ;
180
175
}
176
+ }
177
+
178
+ PyObject * * cnvs = PySequence_Fast_ITEMS (converters );
179
+ for (i = 0 ; i < nargs ; i ++ ) {
180
+ PyObject * cnv = cnvs [i ]; // borrowed ref
181
+ StgDictObject * dict ;
182
+ dict = PyType_stgdict (cnv );
181
183
182
184
if (dict && dict -> getfunc && !_ctypes_simple_instance (cnv )) {
183
185
PyObject * v = dict -> getfunc (* pArgs , dict -> size );
184
186
if (!v ) {
185
187
PrintError ("create argument %zd:\n" , i );
186
- Py_DECREF (cnv );
187
188
goto Done ;
188
189
}
189
- PyTuple_SET_ITEM ( arglist , i , v ) ;
190
+ args [ i ] = v ;
190
191
/* XXX XXX XX
191
192
We have the problem that c_byte or c_short have dict->size of
192
193
1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
@@ -202,23 +203,20 @@ static void _CallPythonObject(void *mem,
202
203
}
203
204
if (!CDataObject_Check (obj )) {
204
205
Py_DECREF (obj );
205
- Py_DECREF (cnv );
206
206
PrintError ("unexpected result of create argument %zd:\n" , i );
207
207
goto Done ;
208
208
}
209
209
memcpy (obj -> b_ptr , * pArgs , dict -> size );
210
- PyTuple_SET_ITEM ( arglist , i , (PyObject * )obj ) ;
210
+ args [ i ] = (PyObject * )obj ;
211
211
#ifdef MS_WIN32
212
212
TryAddRef (dict , obj );
213
213
#endif
214
214
} else {
215
215
PyErr_SetString (PyExc_TypeError ,
216
216
"cannot build parameter" );
217
217
PrintError ("Parsing argument %zd\n" , i );
218
- Py_DECREF (cnv );
219
218
goto Done ;
220
219
}
221
- Py_DECREF (cnv );
222
220
/* XXX error handling! */
223
221
pArgs ++ ;
224
222
}
@@ -241,7 +239,7 @@ static void _CallPythonObject(void *mem,
241
239
#endif
242
240
}
243
241
244
- result = PyObject_CallObject (callable , arglist );
242
+ result = PyObject_Vectorcall (callable , args , nargs , NULL );
245
243
if (result == NULL ) {
246
244
_PyErr_WriteUnraisableMsg ("on calling ctypes callback function" ,
247
245
callable );
@@ -308,7 +306,12 @@ static void _CallPythonObject(void *mem,
308
306
Py_XDECREF (result );
309
307
310
308
Done :
311
- Py_XDECREF (arglist );
309
+ for (j = 0 ; j < i ; j ++ ) {
310
+ Py_DECREF (args [j ]);
311
+ }
312
+ if (args != args_stack ) {
313
+ PyMem_Free (args );
314
+ }
312
315
PyGILState_Release (state );
313
316
}
314
317
@@ -328,12 +331,12 @@ static void closure_fcn(ffi_cif *cif,
328
331
args );
329
332
}
330
333
331
- static CThunkObject * CThunkObject_new (Py_ssize_t nArgs )
334
+ static CThunkObject * CThunkObject_new (Py_ssize_t nargs )
332
335
{
333
336
CThunkObject * p ;
334
337
Py_ssize_t i ;
335
338
336
- p = PyObject_GC_NewVar (CThunkObject , & PyCThunk_Type , nArgs );
339
+ p = PyObject_GC_NewVar (CThunkObject , & PyCThunk_Type , nargs );
337
340
if (p == NULL ) {
338
341
return NULL ;
339
342
}
@@ -348,7 +351,7 @@ static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
348
351
p -> setfunc = NULL ;
349
352
p -> ffi_restype = NULL ;
350
353
351
- for (i = 0 ; i < nArgs + 1 ; ++ i )
354
+ for (i = 0 ; i < nargs + 1 ; ++ i )
352
355
p -> atypes [i ] = NULL ;
353
356
PyObject_GC_Track ((PyObject * )p );
354
357
return p ;
@@ -361,11 +364,12 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
361
364
{
362
365
int result ;
363
366
CThunkObject * p ;
364
- Py_ssize_t nArgs , i ;
367
+ Py_ssize_t nargs , i ;
365
368
ffi_abi cc ;
366
369
367
- nArgs = PySequence_Size (converters );
368
- p = CThunkObject_new (nArgs );
370
+ assert (PyTuple_Check (converters ));
371
+ nargs = PyTuple_GET_SIZE (converters );
372
+ p = CThunkObject_new (nargs );
369
373
if (p == NULL )
370
374
return NULL ;
371
375
@@ -378,12 +382,10 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
378
382
}
379
383
380
384
p -> flags = flags ;
381
- for (i = 0 ; i < nArgs ; ++ i ) {
382
- PyObject * cnv = PySequence_GetItem (converters , i );
383
- if (cnv == NULL )
384
- goto error ;
385
+ PyObject * * cnvs = PySequence_Fast_ITEMS (converters );
386
+ for (i = 0 ; i < nargs ; ++ i ) {
387
+ PyObject * cnv = cnvs [i ]; // borrowed ref
385
388
p -> atypes [i ] = _ctypes_get_ffi_type (cnv );
386
- Py_DECREF (cnv );
387
389
}
388
390
p -> atypes [i ] = NULL ;
389
391
@@ -409,7 +411,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable,
409
411
cc = FFI_STDCALL ;
410
412
#endif
411
413
result = ffi_prep_cif (& p -> cif , cc ,
412
- Py_SAFE_DOWNCAST (nArgs , Py_ssize_t , int ),
414
+ Py_SAFE_DOWNCAST (nargs , Py_ssize_t , int ),
413
415
_ctypes_get_ffi_type (restype ),
414
416
& p -> atypes [0 ]);
415
417
if (result != FFI_OK ) {
0 commit comments