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