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