• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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