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