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