File: | Modules/_ctypes/callbacks.c |
Location: | line 270, column 20 |
Description: | Dereference of undefined pointer value |
1 | #include "Python.h" | ||
2 | #include "frameobject.h" | ||
3 | |||
4 | #include <ffi.h> | ||
5 | #ifdef MS_WIN32 | ||
6 | #include <windows.h> | ||
7 | #endif | ||
8 | #include "ctypes.h" | ||
9 | |||
10 | /**************************************************************/ | ||
11 | |||
12 | static void | ||
13 | CThunkObject_dealloc(PyObject *_self) | ||
14 | { | ||
15 | CThunkObject *self = (CThunkObject *)_self; | ||
16 | Py_XDECREF(self->converters)do { if ((self->converters) == ((void*)0)) ; else do { if ( _Py_RefTotal-- , --((PyObject*)(self->converters))->ob_refcnt != 0) { if (((PyObject*)self->converters)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 16, (PyObject *)(self->converters)); } else _Py_Dealloc( (PyObject *)(self->converters)); } while (0); } while (0); | ||
17 | Py_XDECREF(self->callable)do { if ((self->callable) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(self->callable))->ob_refcnt != 0) { if (((PyObject*)self->callable)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 17, (PyObject *)(self->callable)); } else _Py_Dealloc((PyObject *)(self->callable)); } while (0); } while (0); | ||
18 | Py_XDECREF(self->restype)do { if ((self->restype) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(self->restype))->ob_refcnt != 0) { if (((PyObject*)self->restype)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 18, (PyObject *)(self->restype)); } else _Py_Dealloc((PyObject *)(self->restype)); } while (0); } while (0); | ||
19 | if (self->pcl_write) | ||
20 | ffi_closure_free(self->pcl_write); | ||
21 | PyObject_GC_Del(self); | ||
22 | } | ||
23 | |||
24 | static int | ||
25 | CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg) | ||
26 | { | ||
27 | CThunkObject *self = (CThunkObject *)_self; | ||
28 | Py_VISIT(self->converters)do { if (self->converters) { int vret = visit((PyObject *) (self->converters), arg); if (vret) return vret; } } while (0); | ||
29 | Py_VISIT(self->callable)do { if (self->callable) { int vret = visit((PyObject *)(self ->callable), arg); if (vret) return vret; } } while (0); | ||
30 | Py_VISIT(self->restype)do { if (self->restype) { int vret = visit((PyObject *)(self ->restype), arg); if (vret) return vret; } } while (0); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static int | ||
35 | CThunkObject_clear(PyObject *_self) | ||
36 | { | ||
37 | CThunkObject *self = (CThunkObject *)_self; | ||
38 | Py_CLEAR(self->converters)do { if (self->converters) { PyObject *_py_tmp = (PyObject *)(self->converters); (self->converters) = ((void*)0); do { if (_Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 38, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0); | ||
39 | Py_CLEAR(self->callable)do { if (self->callable) { PyObject *_py_tmp = (PyObject * )(self->callable); (self->callable) = ((void*)0); do { if (_Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0 ) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 39, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0); | ||
40 | Py_CLEAR(self->restype)do { if (self->restype) { PyObject *_py_tmp = (PyObject *) (self->restype); (self->restype) = ((void*)0); do { if ( _Py_RefTotal-- , --((PyObject*)(_py_tmp))->ob_refcnt != 0) { if (((PyObject*)_py_tmp)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 40, (PyObject *)(_py_tmp)); } else _Py_Dealloc((PyObject *) (_py_tmp)); } while (0); } } while (0); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | PyTypeObject PyCThunk_Type = { | ||
45 | PyVarObject_HEAD_INIT(NULL, 0){ { 0, 0, 1, ((void*)0) }, 0 }, | ||
46 | "_ctypes.CThunkObject", | ||
47 | sizeof(CThunkObject), /* tp_basicsize */ | ||
48 | sizeof(ffi_type), /* tp_itemsize */ | ||
49 | CThunkObject_dealloc, /* tp_dealloc */ | ||
50 | 0, /* tp_print */ | ||
51 | 0, /* tp_getattr */ | ||
52 | 0, /* tp_setattr */ | ||
53 | 0, /* tp_reserved */ | ||
54 | 0, /* tp_repr */ | ||
55 | 0, /* tp_as_number */ | ||
56 | 0, /* tp_as_sequence */ | ||
57 | 0, /* tp_as_mapping */ | ||
58 | 0, /* tp_hash */ | ||
59 | 0, /* tp_call */ | ||
60 | 0, /* tp_str */ | ||
61 | 0, /* tp_getattro */ | ||
62 | 0, /* tp_setattro */ | ||
63 | 0, /* tp_as_buffer */ | ||
64 | Py_TPFLAGS_DEFAULT( 0 | (1L<<18) | 0) | Py_TPFLAGS_HAVE_GC(1L<<14), /* tp_flags */ | ||
65 | "CThunkObject", /* tp_doc */ | ||
66 | CThunkObject_traverse, /* tp_traverse */ | ||
67 | CThunkObject_clear, /* tp_clear */ | ||
68 | 0, /* tp_richcompare */ | ||
69 | 0, /* tp_weaklistoffset */ | ||
70 | 0, /* tp_iter */ | ||
71 | 0, /* tp_iternext */ | ||
72 | 0, /* tp_methods */ | ||
73 | 0, /* tp_members */ | ||
74 | }; | ||
75 | |||
76 | /**************************************************************/ | ||
77 | |||
78 | static void | ||
79 | PrintError(char *msg, ...) | ||
80 | { | ||
81 | char buf[512]; | ||
82 | PyObject *f = PySys_GetObject("stderr"); | ||
83 | va_list marker; | ||
84 | |||
85 | va_start(marker, msg)__builtin_va_start(marker, msg); | ||
86 | vsnprintf(buf, sizeof(buf), msg, marker)__builtin___vsnprintf_chk (buf, sizeof(buf), 0, __builtin_object_size (buf, 2 > 1), msg, marker); | ||
87 | va_end(marker)__builtin_va_end(marker); | ||
88 | if (f != NULL((void*)0) && f != Py_None(&_Py_NoneStruct)) | ||
89 | PyFile_WriteString(buf, f); | ||
90 | PyErr_Print(); | ||
91 | } | ||
92 | |||
93 | |||
94 | /* after code that pyrex generates */ | ||
95 | void _ctypes_add_traceback(char *funcname, char *filename, int lineno) | ||
96 | { | ||
97 | PyObject *py_globals = 0; | ||
98 | PyCodeObject *py_code = 0; | ||
99 | PyFrameObject *py_frame = 0; | ||
100 | |||
101 | py_globals = PyDict_New(); | ||
102 | if (!py_globals) goto bad; | ||
103 | py_code = PyCode_NewEmpty(filename, funcname, lineno); | ||
104 | if (!py_code) goto bad; | ||
105 | py_frame = PyFrame_New( | ||
106 | PyThreadState_Get(), /*PyThreadState *tstate,*/ | ||
107 | py_code, /*PyCodeObject *code,*/ | ||
108 | py_globals, /*PyObject *globals,*/ | ||
109 | 0 /*PyObject *locals*/ | ||
110 | ); | ||
111 | if (!py_frame) goto bad; | ||
112 | py_frame->f_lineno = lineno; | ||
113 | PyTraceBack_Here(py_frame); | ||
114 | bad: | ||
115 | Py_XDECREF(py_globals)do { if ((py_globals) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_globals))->ob_refcnt != 0) { if ((( PyObject*)py_globals)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 115, (PyObject *)(py_globals)); } else _Py_Dealloc((PyObject *)(py_globals)); } while (0); } while (0); | ||
116 | Py_XDECREF(py_code)do { if ((py_code) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_code))->ob_refcnt != 0) { if (((PyObject *)py_code)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 116, (PyObject *)(py_code)); } else _Py_Dealloc((PyObject * )(py_code)); } while (0); } while (0); | ||
117 | Py_XDECREF(py_frame)do { if ((py_frame) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_frame))->ob_refcnt != 0) { if (((PyObject *)py_frame)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 117, (PyObject *)(py_frame)); } else _Py_Dealloc((PyObject * )(py_frame)); } while (0); } while (0); | ||
118 | } | ||
119 | |||
120 | #ifdef MS_WIN32 | ||
121 | /* | ||
122 | * We must call AddRef() on non-NULL COM pointers we receive as arguments | ||
123 | * to callback functions - these functions are COM method implementations. | ||
124 | * The Python instances we create have a __del__ method which calls Release(). | ||
125 | * | ||
126 | * The presence of a class attribute named '_needs_com_addref_' triggers this | ||
127 | * behaviour. It would also be possible to call the AddRef() Python method, | ||
128 | * after checking for PyObject_IsTrue(), but this would probably be somewhat | ||
129 | * slower. | ||
130 | */ | ||
131 | static void | ||
132 | TryAddRef(StgDictObject *dict, CDataObject *obj) | ||
133 | { | ||
134 | IUnknown *punk; | ||
135 | |||
136 | if (NULL((void*)0) == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_")) | ||
137 | return; | ||
138 | |||
139 | punk = *(IUnknown **)obj->b_ptr; | ||
140 | if (punk) | ||
141 | punk->lpVtbl->AddRef(punk); | ||
142 | return; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | /****************************************************************************** | ||
147 | * | ||
148 | * Call the python object with all arguments | ||
149 | * | ||
150 | */ | ||
151 | static void _CallPythonObject(void *mem, | ||
152 | ffi_type *restype, | ||
153 | SETFUNC setfunc, | ||
154 | PyObject *callable, | ||
155 | PyObject *converters, | ||
156 | int flags, | ||
157 | void **pArgs) | ||
158 | { | ||
159 | Py_ssize_t i; | ||
160 | PyObject *result; | ||
161 | PyObject *arglist = NULL((void*)0); | ||
162 | Py_ssize_t nArgs; | ||
163 | PyObject *error_object = NULL((void*)0); | ||
164 | int *space; | ||
165 | #ifdef WITH_THREAD1 | ||
166 | PyGILState_STATE state = PyGILState_Ensure(); | ||
167 | #endif | ||
168 | |||
169 | nArgs = PySequence_LengthPySequence_Size(converters); | ||
170 | /* Hm. What to return in case of error? | ||
171 | For COM, 0xFFFFFFFF seems better than 0. | ||
172 | */ | ||
173 | if (nArgs < 0) { | ||
| |||
174 | PrintError("BUG: PySequence_Length"); | ||
175 | goto Done; | ||
176 | } | ||
177 | |||
178 | arglist = PyTuple_New(nArgs); | ||
179 | if (!arglist) { | ||
| |||
180 | PrintError("PyTuple_New()"); | ||
181 | goto Done; | ||
182 | } | ||
183 | for (i = 0; i < nArgs; ++i) { | ||
| |||
184 | /* Note: new reference! */ | ||
185 | PyObject *cnv = PySequence_GetItem(converters, i); | ||
186 | StgDictObject *dict; | ||
187 | if (cnv) | ||
188 | dict = PyType_stgdict(cnv); | ||
189 | else { | ||
190 | PrintError("Getting argument converter %d\n", i); | ||
191 | goto Done; | ||
192 | } | ||
193 | |||
194 | if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) { | ||
195 | PyObject *v = dict->getfunc(*pArgs, dict->size); | ||
196 | if (!v) { | ||
197 | PrintError("create argument %d:\n", i); | ||
198 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 198, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
199 | goto Done; | ||
200 | } | ||
201 | PyTuple_SET_ITEM(arglist, i, v)(((PyTupleObject *)(arglist))->ob_item[i] = v); | ||
202 | /* XXX XXX XX | ||
203 | We have the problem that c_byte or c_short have dict->size of | ||
204 | 1 resp. 4, but these parameters are pushed as sizeof(int) bytes. | ||
205 | BTW, the same problem occurrs when they are pushed as parameters | ||
206 | */ | ||
207 | } else if (dict) { | ||
208 | /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */ | ||
209 | CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL((void*)0)); | ||
210 | if (!obj) { | ||
211 | PrintError("create argument %d:\n", i); | ||
212 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 212, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
213 | goto Done; | ||
214 | } | ||
215 | if (!CDataObject_Check(obj)((((PyObject*)(obj))->ob_type) == (&PyCData_Type) || PyType_IsSubtype ((((PyObject*)(obj))->ob_type), (&PyCData_Type)))) { | ||
216 | Py_DECREF(obj)do { if (_Py_RefTotal-- , --((PyObject*)(obj))->ob_refcnt != 0) { if (((PyObject*)obj)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 216, (PyObject *)(obj)); } else _Py_Dealloc((PyObject *)(obj )); } while (0); | ||
217 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 217, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
218 | PrintError("unexpected result of create argument %d:\n", i); | ||
219 | goto Done; | ||
220 | } | ||
221 | memcpy(obj->b_ptr, *pArgs, dict->size)((__builtin_object_size (obj->b_ptr, 0) != (size_t) -1) ? __builtin___memcpy_chk (obj->b_ptr, *pArgs, dict->size, __builtin_object_size (obj->b_ptr, 0)) : __inline_memcpy_chk (obj->b_ptr, *pArgs , dict->size)); | ||
222 | PyTuple_SET_ITEM(arglist, i, (PyObject *)obj)(((PyTupleObject *)(arglist))->ob_item[i] = (PyObject *)obj ); | ||
223 | #ifdef MS_WIN32 | ||
224 | TryAddRef(dict, obj); | ||
225 | #endif | ||
226 | } else { | ||
227 | PyErr_SetString(PyExc_TypeError, | ||
228 | "cannot build parameter"); | ||
229 | PrintError("Parsing argument %d\n", i); | ||
230 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 230, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
231 | goto Done; | ||
232 | } | ||
233 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 233, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
234 | /* XXX error handling! */ | ||
235 | pArgs++; | ||
236 | } | ||
237 | |||
238 | #define CHECK(what, x)if (x == ((void*)0)) _ctypes_add_traceback(what, "_ctypes/callbacks.c" , 238 - 1), PyErr_Print() \ | ||
239 | if (x == NULL((void*)0)) _ctypes_add_traceback(what, "_ctypes/callbacks.c", __LINE__239 - 1), PyErr_Print() | ||
240 | |||
241 | if (flags & (FUNCFLAG_USE_ERRNO0x8 | FUNCFLAG_USE_LASTERROR0x10)) { | ||
| |||
242 | error_object = _ctypes_get_errobj(&space); | ||
243 | if (error_object == NULL((void*)0)) | ||
244 | goto Done; | ||
245 | if (flags & FUNCFLAG_USE_ERRNO0x8) { | ||
246 | int temp = space[0]; | ||
247 | space[0] = errno(*__error()); | ||
248 | errno(*__error()) = temp; | ||
249 | } | ||
250 | #ifdef MS_WIN32 | ||
251 | if (flags & FUNCFLAG_USE_LASTERROR0x10) { | ||
252 | int temp = space[1]; | ||
253 | space[1] = GetLastError(); | ||
254 | SetLastError(temp); | ||
255 | } | ||
256 | #endif | ||
257 | } | ||
258 | |||
259 | result = PyObject_CallObject(callable, arglist); | ||
260 | CHECK("'calling callback function'", result)if (result == ((void*)0)) _ctypes_add_traceback("'calling callback function'" , "_ctypes/callbacks.c", 260 - 1), PyErr_Print(); | ||
261 | |||
262 | #ifdef MS_WIN32 | ||
263 | if (flags & FUNCFLAG_USE_LASTERROR0x10) { | ||
264 | int temp = space[1]; | ||
265 | space[1] = GetLastError(); | ||
266 | SetLastError(temp); | ||
267 | } | ||
268 | #endif | ||
269 | if (flags & FUNCFLAG_USE_ERRNO0x8) { | ||
| |||
270 | int temp = space[0]; | ||
| |||
271 | space[0] = errno(*__error()); | ||
272 | errno(*__error()) = temp; | ||
273 | } | ||
274 | Py_XDECREF(error_object)do { if ((error_object) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(error_object))->ob_refcnt != 0) { if ( ((PyObject*)error_object)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 274, (PyObject *)(error_object)); } else _Py_Dealloc((PyObject *)(error_object)); } while (0); } while (0); | ||
275 | |||
276 | if ((restype != &ffi_type_void) && result) { | ||
277 | PyObject *keep; | ||
278 | assert(setfunc)(__builtin_expect(!(setfunc), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 278, "setfunc") : (void)0); | ||
279 | #ifdef WORDS_BIGENDIAN | ||
280 | /* See the corresponding code in callproc.c, around line 961 */ | ||
281 | if (restype->type != FFI_TYPE_FLOAT2 && restype->size < sizeof(ffi_arg)) | ||
282 | mem = (char *)mem + sizeof(ffi_arg) - restype->size; | ||
283 | #endif | ||
284 | keep = setfunc(mem, result, 0); | ||
285 | CHECK("'converting callback result'", keep)if (keep == ((void*)0)) _ctypes_add_traceback("'converting callback result'" , "_ctypes/callbacks.c", 285 - 1), PyErr_Print(); | ||
286 | /* keep is an object we have to keep alive so that the result | ||
287 | stays valid. If there is no such object, the setfunc will | ||
288 | have returned Py_None. | ||
289 | |||
290 | If there is such an object, we have no choice than to keep | ||
291 | it alive forever - but a refcount and/or memory leak will | ||
292 | be the result. EXCEPT when restype is py_object - Python | ||
293 | itself knows how to manage the refcount of these objects. | ||
294 | */ | ||
295 | if (keep == NULL((void*)0)) /* Could not convert callback result. */ | ||
296 | PyErr_WriteUnraisable(callable); | ||
297 | else if (keep == Py_None(&_Py_NoneStruct)) /* Nothing to keep */ | ||
298 | Py_DECREF(keep)do { if (_Py_RefTotal-- , --((PyObject*)(keep))->ob_refcnt != 0) { if (((PyObject*)keep)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 298, (PyObject *)(keep)); } else _Py_Dealloc((PyObject *)(keep )); } while (0); | ||
299 | else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { | ||
300 | if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning, | ||
301 | "memory leak in callback function.", | ||
302 | 1)) | ||
303 | PyErr_WriteUnraisable(callable); | ||
304 | } | ||
305 | } | ||
306 | Py_XDECREF(result)do { if ((result) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject *)result)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 306, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0); } while (0); | ||
307 | Done: | ||
308 | Py_XDECREF(arglist)do { if ((arglist) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(arglist))->ob_refcnt != 0) { if (((PyObject *)arglist)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 308, (PyObject *)(arglist)); } else _Py_Dealloc((PyObject * )(arglist)); } while (0); } while (0); | ||
309 | #ifdef WITH_THREAD1 | ||
310 | PyGILState_Release(state); | ||
311 | #endif | ||
312 | } | ||
313 | |||
314 | static void closure_fcn(ffi_cif *cif, | ||
315 | void *resp, | ||
316 | void **args, | ||
317 | void *userdata) | ||
318 | { | ||
319 | CThunkObject *p = (CThunkObject *)userdata; | ||
320 | |||
321 | _CallPythonObject(resp, | ||
322 | p->ffi_restype, | ||
323 | p->setfunc, | ||
324 | p->callable, | ||
325 | p->converters, | ||
326 | p->flags, | ||
327 | args); | ||
328 | } | ||
329 | |||
330 | static CThunkObject* CThunkObject_new(Py_ssize_t nArgs) | ||
331 | { | ||
332 | CThunkObject *p; | ||
333 | int i; | ||
334 | |||
335 | p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs)( (CThunkObject *) _PyObject_GC_NewVar((&PyCThunk_Type), ( nArgs)) ); | ||
336 | if (p == NULL((void*)0)) { | ||
337 | PyErr_NoMemory(); | ||
338 | return NULL((void*)0); | ||
339 | } | ||
340 | |||
341 | p->pcl_exec = NULL((void*)0); | ||
342 | p->pcl_write = NULL((void*)0); | ||
343 | memset(&p->cif, 0, sizeof(p->cif))((__builtin_object_size (&p->cif, 0) != (size_t) -1) ? __builtin___memset_chk (&p->cif, 0, sizeof(p->cif) , __builtin_object_size (&p->cif, 0)) : __inline_memset_chk (&p->cif, 0, sizeof(p->cif))); | ||
344 | p->converters = NULL((void*)0); | ||
345 | p->callable = NULL((void*)0); | ||
346 | p->setfunc = NULL((void*)0); | ||
347 | p->ffi_restype = NULL((void*)0); | ||
348 | |||
349 | for (i = 0; i < nArgs + 1; ++i) | ||
350 | p->atypes[i] = NULL((void*)0); | ||
351 | PyObject_GC_Track((PyObject *)p); | ||
352 | return p; | ||
353 | } | ||
354 | |||
355 | CThunkObject *_ctypes_alloc_callback(PyObject *callable, | ||
356 | PyObject *converters, | ||
357 | PyObject *restype, | ||
358 | int flags) | ||
359 | { | ||
360 | int result; | ||
361 | CThunkObject *p; | ||
362 | Py_ssize_t nArgs, i; | ||
363 | ffi_abi cc; | ||
364 | |||
365 | nArgs = PySequence_Size(converters); | ||
366 | p = CThunkObject_new(nArgs); | ||
367 | if (p == NULL((void*)0)) | ||
368 | return NULL((void*)0); | ||
369 | |||
370 | assert(CThunk_CheckExact((PyObject *)p))(__builtin_expect(!((((PyObject *)p)->ob_type == &PyCThunk_Type )), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 370, "CThunk_CheckExact((PyObject *)p)") : (void)0); | ||
371 | |||
372 | p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure), | ||
373 | &p->pcl_exec); | ||
374 | if (p->pcl_write == NULL((void*)0)) { | ||
375 | PyErr_NoMemory(); | ||
376 | goto error; | ||
377 | } | ||
378 | |||
379 | p->flags = flags; | ||
380 | for (i = 0; i < nArgs; ++i) { | ||
381 | PyObject *cnv = PySequence_GetItem(converters, i); | ||
382 | if (cnv == NULL((void*)0)) | ||
383 | goto error; | ||
384 | p->atypes[i] = _ctypes_get_ffi_type(cnv); | ||
385 | Py_DECREF(cnv)do { if (_Py_RefTotal-- , --((PyObject*)(cnv))->ob_refcnt != 0) { if (((PyObject*)cnv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 385, (PyObject *)(cnv)); } else _Py_Dealloc((PyObject *)(cnv )); } while (0); | ||
386 | } | ||
387 | p->atypes[i] = NULL((void*)0); | ||
388 | |||
389 | Py_INCREF(restype)( _Py_RefTotal++ , ((PyObject*)(restype))->ob_refcnt++); | ||
390 | p->restype = restype; | ||
391 | if (restype == Py_None(&_Py_NoneStruct)) { | ||
392 | p->setfunc = NULL((void*)0); | ||
393 | p->ffi_restype = &ffi_type_void; | ||
394 | } else { | ||
395 | StgDictObject *dict = PyType_stgdict(restype); | ||
396 | if (dict == NULL((void*)0) || dict->setfunc == NULL((void*)0)) { | ||
397 | PyErr_SetString(PyExc_TypeError, | ||
398 | "invalid result type for callback function"); | ||
399 | goto error; | ||
400 | } | ||
401 | p->setfunc = dict->setfunc; | ||
402 | p->ffi_restype = &dict->ffi_type_pointer; | ||
403 | } | ||
404 | |||
405 | cc = FFI_DEFAULT_ABI; | ||
406 | #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) | ||
407 | if ((flags & FUNCFLAG_CDECL0x1) == 0) | ||
408 | cc = FFI_STDCALL; | ||
409 | #endif | ||
410 | result = ffi_prep_cif(&p->cif, cc, | ||
411 | Py_SAFE_DOWNCAST(nArgs, Py_ssize_t, int)((__builtin_expect(!((Py_ssize_t)(int)(nArgs) == (nArgs)), 0) ? __assert_rtn(__func__, "/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 411, "(Py_ssize_t)(int)(nArgs) == (nArgs)") : (void)0), (int )(nArgs)), | ||
412 | _ctypes_get_ffi_type(restype), | ||
413 | &p->atypes[0]); | ||
414 | if (result != FFI_OK) { | ||
415 | PyErr_Format(PyExc_RuntimeError, | ||
416 | "ffi_prep_cif failed with %d", result); | ||
417 | goto error; | ||
418 | } | ||
419 | #if defined(X86_DARWIN) || defined(POWERPC_DARWIN) | ||
420 | result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); | ||
421 | #else | ||
422 | result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, | ||
423 | p, | ||
424 | p->pcl_exec); | ||
425 | #endif | ||
426 | if (result != FFI_OK) { | ||
427 | PyErr_Format(PyExc_RuntimeError, | ||
428 | "ffi_prep_closure failed with %d", result); | ||
429 | goto error; | ||
430 | } | ||
431 | |||
432 | Py_INCREF(converters)( _Py_RefTotal++ , ((PyObject*)(converters))->ob_refcnt++); | ||
433 | p->converters = converters; | ||
434 | Py_INCREF(callable)( _Py_RefTotal++ , ((PyObject*)(callable))->ob_refcnt++); | ||
435 | p->callable = callable; | ||
436 | return p; | ||
437 | |||
438 | error: | ||
439 | Py_XDECREF(p)do { if ((p) == ((void*)0)) ; else do { if (_Py_RefTotal-- , -- ((PyObject*)(p))->ob_refcnt != 0) { if (((PyObject*)p)-> ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 439, (PyObject *)(p)); } else _Py_Dealloc((PyObject *)(p)); } while (0); } while (0); | ||
440 | return NULL((void*)0); | ||
441 | } | ||
442 | |||
443 | #ifdef MS_WIN32 | ||
444 | |||
445 | static void LoadPython(void) | ||
446 | { | ||
447 | if (!Py_IsInitialized()) { | ||
448 | #ifdef WITH_THREAD1 | ||
449 | PyEval_InitThreads(); | ||
450 | #endif | ||
451 | Py_Initialize(); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | /******************************************************************/ | ||
456 | |||
457 | long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) | ||
458 | { | ||
459 | PyObject *mod, *func, *result; | ||
460 | long retval; | ||
461 | static PyObject *context; | ||
462 | |||
463 | if (context == NULL((void*)0)) | ||
464 | context = PyUnicode_InternFromString("_ctypes.DllGetClassObject"); | ||
465 | |||
466 | mod = PyImport_ImportModuleNoBlock("ctypes"); | ||
467 | if (!mod) { | ||
468 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
469 | /* There has been a warning before about this already */ | ||
470 | return E_FAIL; | ||
471 | } | ||
472 | |||
473 | func = PyObject_GetAttrString(mod, "DllGetClassObject"); | ||
474 | Py_DECREF(mod)do { if (_Py_RefTotal-- , --((PyObject*)(mod))->ob_refcnt != 0) { if (((PyObject*)mod)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 474, (PyObject *)(mod)); } else _Py_Dealloc((PyObject *)(mod )); } while (0); | ||
475 | if (!func) { | ||
476 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
477 | return E_FAIL; | ||
478 | } | ||
479 | |||
480 | { | ||
481 | PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid); | ||
482 | PyObject *py_riid = PyLong_FromVoidPtr((void *)riid); | ||
483 | PyObject *py_ppv = PyLong_FromVoidPtr(ppv); | ||
484 | if (!py_rclsid || !py_riid || !py_ppv) { | ||
485 | Py_XDECREF(py_rclsid)do { if ((py_rclsid) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_rclsid))->ob_refcnt != 0) { if (((PyObject *)py_rclsid)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 485, (PyObject *)(py_rclsid)); } else _Py_Dealloc((PyObject *)(py_rclsid)); } while (0); } while (0); | ||
486 | Py_XDECREF(py_riid)do { if ((py_riid) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_riid))->ob_refcnt != 0) { if (((PyObject *)py_riid)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 486, (PyObject *)(py_riid)); } else _Py_Dealloc((PyObject * )(py_riid)); } while (0); } while (0); | ||
487 | Py_XDECREF(py_ppv)do { if ((py_ppv) == ((void*)0)) ; else do { if (_Py_RefTotal -- , --((PyObject*)(py_ppv))->ob_refcnt != 0) { if (((PyObject *)py_ppv)->ob_refcnt < 0) _Py_NegativeRefcount("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 487, (PyObject *)(py_ppv)); } else _Py_Dealloc((PyObject *) (py_ppv)); } while (0); } while (0); | ||
488 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 488, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0); | ||
489 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
490 | return E_FAIL; | ||
491 | } | ||
492 | result = PyObject_CallFunctionObjArgs(func, | ||
493 | py_rclsid, | ||
494 | py_riid, | ||
495 | py_ppv, | ||
496 | NULL((void*)0)); | ||
497 | Py_DECREF(py_rclsid)do { if (_Py_RefTotal-- , --((PyObject*)(py_rclsid))->ob_refcnt != 0) { if (((PyObject*)py_rclsid)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 497, (PyObject *)(py_rclsid)); } else _Py_Dealloc((PyObject *)(py_rclsid)); } while (0); | ||
498 | Py_DECREF(py_riid)do { if (_Py_RefTotal-- , --((PyObject*)(py_riid))->ob_refcnt != 0) { if (((PyObject*)py_riid)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 498, (PyObject *)(py_riid)); } else _Py_Dealloc((PyObject * )(py_riid)); } while (0); | ||
499 | Py_DECREF(py_ppv)do { if (_Py_RefTotal-- , --((PyObject*)(py_ppv))->ob_refcnt != 0) { if (((PyObject*)py_ppv)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 499, (PyObject *)(py_ppv)); } else _Py_Dealloc((PyObject *) (py_ppv)); } while (0); | ||
500 | } | ||
501 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 501, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0); | ||
502 | if (!result) { | ||
503 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
504 | return E_FAIL; | ||
505 | } | ||
506 | |||
507 | retval = PyLong_AsLong(result); | ||
508 | if (PyErr_Occurred()) { | ||
509 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
510 | retval = E_FAIL; | ||
511 | } | ||
512 | Py_DECREF(result)do { if (_Py_RefTotal-- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject*)result)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 512, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0); | ||
513 | return retval; | ||
514 | } | ||
515 | |||
516 | STDAPI DllGetClassObject(REFCLSID rclsid, | ||
517 | REFIID riid, | ||
518 | LPVOID *ppv) | ||
519 | { | ||
520 | long result; | ||
521 | #ifdef WITH_THREAD1 | ||
522 | PyGILState_STATE state; | ||
523 | #endif | ||
524 | |||
525 | LoadPython(); | ||
526 | #ifdef WITH_THREAD1 | ||
527 | state = PyGILState_Ensure(); | ||
528 | #endif | ||
529 | result = Call_GetClassObject(rclsid, riid, ppv); | ||
530 | #ifdef WITH_THREAD1 | ||
531 | PyGILState_Release(state); | ||
532 | #endif | ||
533 | return result; | ||
534 | } | ||
535 | |||
536 | long Call_CanUnloadNow(void) | ||
537 | { | ||
538 | PyObject *mod, *func, *result; | ||
539 | long retval; | ||
540 | static PyObject *context; | ||
541 | |||
542 | if (context == NULL((void*)0)) | ||
543 | context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow"); | ||
544 | |||
545 | mod = PyImport_ImportModuleNoBlock("ctypes"); | ||
546 | if (!mod) { | ||
547 | /* OutputDebugString("Could not import ctypes"); */ | ||
548 | /* We assume that this error can only occur when shutting | ||
549 | down, so we silently ignore it */ | ||
550 | PyErr_Clear(); | ||
551 | return E_FAIL; | ||
552 | } | ||
553 | /* Other errors cannot be raised, but are printed to stderr */ | ||
554 | func = PyObject_GetAttrString(mod, "DllCanUnloadNow"); | ||
555 | Py_DECREF(mod)do { if (_Py_RefTotal-- , --((PyObject*)(mod))->ob_refcnt != 0) { if (((PyObject*)mod)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 555, (PyObject *)(mod)); } else _Py_Dealloc((PyObject *)(mod )); } while (0); | ||
556 | if (!func) { | ||
557 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
558 | return E_FAIL; | ||
559 | } | ||
560 | |||
561 | result = PyObject_CallFunction(func, NULL((void*)0)); | ||
562 | Py_DECREF(func)do { if (_Py_RefTotal-- , --((PyObject*)(func))->ob_refcnt != 0) { if (((PyObject*)func)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 562, (PyObject *)(func)); } else _Py_Dealloc((PyObject *)(func )); } while (0); | ||
563 | if (!result) { | ||
564 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
565 | return E_FAIL; | ||
566 | } | ||
567 | |||
568 | retval = PyLong_AsLong(result); | ||
569 | if (PyErr_Occurred()) { | ||
570 | PyErr_WriteUnraisable(context ? context : Py_None(&_Py_NoneStruct)); | ||
571 | retval = E_FAIL; | ||
572 | } | ||
573 | Py_DECREF(result)do { if (_Py_RefTotal-- , --((PyObject*)(result))->ob_refcnt != 0) { if (((PyObject*)result)->ob_refcnt < 0) _Py_NegativeRefcount ("/Users/brett/Dev/python/3.x/py3k/Modules/_ctypes/callbacks.c" , 573, (PyObject *)(result)); } else _Py_Dealloc((PyObject *) (result)); } while (0); | ||
574 | return retval; | ||
575 | } | ||
576 | |||
577 | /* | ||
578 | DllRegisterServer and DllUnregisterServer still missing | ||
579 | */ | ||
580 | |||
581 | STDAPI DllCanUnloadNow(void) | ||
582 | { | ||
583 | long result; | ||
584 | #ifdef WITH_THREAD1 | ||
585 | PyGILState_STATE state = PyGILState_Ensure(); | ||
586 | #endif | ||
587 | result = Call_CanUnloadNow(); | ||
588 | #ifdef WITH_THREAD1 | ||
589 | PyGILState_Release(state); | ||
590 | #endif | ||
591 | return result; | ||
592 | } | ||
593 | |||
594 | #ifndef Py_NO_ENABLE_SHARED | ||
595 | BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes) | ||
596 | { | ||
597 | switch(fdwReason) { | ||
598 | case DLL_PROCESS_ATTACH: | ||
599 | DisableThreadLibraryCalls(hinstDLL); | ||
600 | break; | ||
601 | } | ||
602 | return TRUE; | ||
603 | } | ||
604 | #endif | ||
605 | |||
606 | #endif | ||
607 | |||
608 | /* | ||
609 | Local Variables: | ||
610 | compile-command: "cd .. && python setup.py -q build_ext" | ||
611 | End: | ||
612 | */ |