ยปCore Development>Code coverage>Modules/_ctypes/callbacks.c

Python code coverage for Modules/_ctypes/callbacks.c

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